ipywidgets
ipywidgets copied to clipboard
bug: selected_index of Tab widget after changing children and setting selected_index incorrect
After changing the children and setting the selected_index attribute to the value it had before, selected_index is set to 0.
Code to reproduce:
import ipywidgets
tabs = ipywidgets.Tab()
tabs.children = [ipywidgets.Label(value='tab1'), ipywidgets.Label(value='tab2')]
tabs.observe(lambda change: print(f"selected index: {change['new']}") , names='selected_index')
def change_children(_):
tabs.children = [ipywidgets.Label(value='tab1'), ipywidgets.Label(value='tab2')]
tabs.selected_index = 1
btn = ipywidgets.Button(description='change_children')
btn.on_click(change_children)
ipywidgets.VBox([tabs, btn])
@mariobuikhuizen did you find any sort of workaround for this issue? I am experiencing something similar.
Hi,
Same thing for me ... but I've found a workaround ;) ! Before changing the children attribute, you should reset the selected_index with : tabs.selected_index = None
I put the modified example below.
import ipywidgets
tabs = ipywidgets.Tab()
tabs.children = [ipywidgets.Label(value='tab1'), ipywidgets.Label(value='tab2'), ipywidgets.Label(value='tab3'), ipywidgets.Label(value='tab4')]
tabs.observe(lambda change: print(f"selected index: {change['new']}") , names='selected_index')
def change_children(_):
id = tabs.selected_index
tabs.selected_index = None # Warning : this will emit a change event
tabs.children = [ipywidgets.Label(value='tab1'), ipywidgets.Label(value='tab2'), ipywidgets.Label(value='tab3'), ipywidgets.Label(value='tab4')]
tabs.selected_index = id
btn = ipywidgets.Button(description='change_children')
btn.on_click(change_children)
ipywidgets.VBox([tabs, btn])
I also came across this issue, but I have the additional complication that I want to set tabs.children
from an observer to selected_index
. This would result in an infinite recursion in @ph-pi 's workaround. My use case is to wrap Tabs
into something where only a limited number of tabs is displayed and the active tab is always the middle tab (imagine the tabs being on turnable wheel). Any input on how to achieve this is
One pattern to break an infinite loop is to create a variable that both observers can see, and in one observer set the variable, do the change which triggers the other observer, then reset the variable back. In the other observer, check the value of that variable before deciding what to do. Essentially, the variable is a way for the two observers to communicate about what they are currently doing.