weixin_39857211
weixin_39857211
2020-12-01 17:56

Change Tab content when button on_click event

Hi all,

Is it possible to change the content of a tab in Tab widget when a button is clicked? I tried dozens of times to change the definition of a tab to display a different widget in the same tab when a button is clicked but it seems that the tab doesn´t admit changes after definition:

The original is: a = ipywidgets.VBox([textbox1, ipywidgets.HBox([slider1,slider2],layout=item_layout)],layout=item_layout)

And when a button is clicked, change the elements in the tab:

a = ipywidgets.VBox([textbox2, ipywidgets.HBox([textbox3,slider3],layout=item_layout)],layout=item_layout)

I implement the definition in the on_click eventhandler but it seems that the new definition is not communicated outside.

Thanks for your help!

该提问来源于开源项目:jupyter-widgets/ipywidgets

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

6条回答

  • weixin_39785600 weixin_39785600 4月前

    Hi! Could you provide more code to replicate your issue?

    It looks like it works on my side using the following code:

    python
    from ipywidgets import Button, Tab, IntSlider, VBox
    
    tab = Tab()
    
    button = Button(description='Add slider!')
    
    def on_button_click(event):
        tab.children = tab.children + (IntSlider(), )
    
    button.on_click(on_button_click)
    
    VBox((button, tab))
    
    点赞 评论 复制链接分享
  • weixin_39857211 weixin_39857211 4月前

    Hi Martin!

    Thanks for your answer. The solution I'm thinking is a little bit different from yours:

    Following your code, what I want to do is to create a tab, put an element inside that tab and, clicking a button, change or substitute that element by another element. In this case a slider by a button.

    
    from ipywidgets import Button, Tab, IntSlider, VBox
    
    button = Button(description='Add button!')
    slider1 = IntSlider()
    button2 = Button(description='one button')
    tab = Tab([slider1])
    
    def on_button_click(event):
        #tab.children = tab.children + (IntSlider(), )
        global tab
        tab = Tab([button2])
    
    button.on_click(on_button_click)
    
    VBox((button, tab))
    

    Once I click "Add button!", nothing happens.

    Thanks++!

    点赞 评论 复制链接分享
  • weixin_39785600 weixin_39785600 4月前

    The issue is that when you do tab = Tab([button2]) in your callback, you redefine the tab variable, but the VBox still has the initial value.

    One way to fix your code is to keep a reference to the VBox object, and reassigning its children in the callback:

    python
    from ipywidgets import Button, Tab, IntSlider, VBox
    
    button = Button(description='Add button!')
    slider1 = IntSlider()
    button2 = Button(description='one button')
    tab = Tab([slider1])
    
    box = VBox((button, tab))
    
    def on_button_click(event):
        global box
        box.children[1] = Tab([button2])
    
        # Make a copy of the children, so that ipywidgets is notified that the children value has changed
        box.children = (child for child in box.children)
    
    button.on_click(on_button_click)
    
    box
    
    点赞 评论 复制链接分享
  • weixin_39857211 weixin_39857211 4月前

    Sorry Martin but it seems that the box.children assign inside the method is failing, because the object doesn´t support assignment.

    I'm thinking maybe to use accordions but is far to be optimal when the idea is to use only one tab (for that functionality) and simply change the widgets inside it.

    Thanks,

    点赞 评论 复制链接分享
  • weixin_39785600 weixin_39785600 4月前

    I have to admit I did not test the code and it's indeed not working due to tuple item assignment, this version does what you want:

    python
    from ipywidgets import Button, Tab, IntSlider, VBox
    
    button = Button(description='Add button!')
    slider1 = IntSlider()
    button2 = Button(description='one button')
    tab = Tab([slider1])
    
    box = VBox((button, tab))
    
    def on_button_click(event):
        global box
    
        # Make a copy of the children, so that ipywidgets is notified that the children value has changed
        new_children = [child for child in box.children]
    
        new_children[1] = Tab([button2])
    
        box.children = new_children
    
    button.on_click(on_button_click)
    
    box
    
    点赞 评论 复制链接分享
  • weixin_39857211 weixin_39857211 4月前

    Amazing Martin! works 10/10!

    Many thanks!

    点赞 评论 复制链接分享