I find it quite unpythonic to have to write
tabs = w.Tab(children=outputs)
for i, title in enumerate(titles):
tabs.set_title(i, title)
Where, we should just be able to write:
tabs = w.Tab(children=outputs, titles=titles)
While I'm here, I'd also like to propose a Tab interface for capturing general output in a clean way (I also think this could apply to other containers such as Grid, etc.):
from IPython.display import display, Image
tabs = Tab()
for f in glob.glob('results/*.png'):
with tabs.add_tab(title=f):
print(f)
display(Image(filename=f))
# Here it is implemented, but it would be great to have something like this
# supported off the shelf
from contextlib import contextmanager
import ipywidgets.widgets as w
class Tab(w.Tab):
@contextmanager
def add_tab(self, title=None):
out = w.Output()
self.children += (out,)
if title:
self.set_title(len(self.children) - 1, title)
with out:
yield
Where, we should just be able to write:
tabs = w.Tab(children=outputs, titles=titles)
+1. It's bothered me for a long time that we have get_title and set_title.
Additionally, looking at the code, it's weird that titles is a dictionary indexed with integers, instead of just a tuple corresponding to the children. I think we could expose a tuple interface to users (along with constructor attribute) in a backwards-compatible way (i.e., changes to the tuple would change the dict that is synced), and we could eliminate the dict in 8.0.
Using a 'titles' parameter at instantiation time has these effects:
Assigning a list of titles to widget.titles has these effects:
Only widget.set_title method actually sets the titles to a widget with children, yet:
Environment:
Python ver: 3.7.6
OS: win32 [MSC v.1916 64 bit (AMD64)]
ipywidgets: 7.5.1
JupyterLab: 2.2.6
import ipywidgets as widgets
def prt_title_attr(obj, attr='titles'):
print(attr + ' attribute:',
getattr(obj,attr,'No such attribute!'),'\n')
# Tab widget:
tab_contents = ['P0', 'P1']
children = [widgets.Text(description=name) for name in tab_contents]
print("1.1 docstring_tab1: title list assigned to parameter `titles` at instantiation:")
docstring_tab1 = widgets.Tab(children = children,
titles = [str(i) for i in range(len(children))])
docstring_tab1
prt_title_attr(docstring_tab1)
print("1.2 docstring_tab2: title list assigned to `docstring_tab2.titles`:")
docstring_tab2 = widgets.Tab()
docstring_tab2.children = children
docstring_tab2.titles = [str(i) for i in range(len(children))]
docstring_tab2
prt_title_attr(docstring_tab2)
# Only the .set_title method produces expected results:
print("2. working_tab: tab title assigned via `.set_title()`:")
working_tab = ipw.Tab()
working_tab.children = children
for i in range(len(children)):
working_tab.set_title(i, 'Tab ' + str(i))
working_tab
prt_title_attr(working_tab)
# Accordion widget:
print("3.1 docstring_acc1: title list assigned to parameter `titles` at instantiation:")
docstring_acc1 = widgets.Accordion(children=children,
titles=[str(i) for i in range(len(children))])
docstring_acc1
prt_title_attr(docstring_acc1)
print("3.2 docstring_acc2: title list assigned to `docstring_acc2.titles`:")
docstring_acc2 = widgets.Accordion()
docstring_acc2.children = children
docstring_acc2.titles = [str(i) for i in range(len(children))]
docstring_acc2
prt_title_attr(docstring_acc2)
print("4 working_acc: title list assigned via `.set_title()`:")
working_acc = widgets.Accordion()
working_acc.children = children
# or working_acc = widgets.Accordion(children = children)
for i in range(len(children)):
working_acc.set_title(i, 'Acc ' + str(i))
working_acc
prt_title_attr(working_acc)

The .titles attribute is in ipywidgets 8.0, which has not been released yet. ipywidgets 7.x still uses the set_title method.
This issue was fixed in https://github.com/jupyter-widgets/ipywidgets/pull/2746 and will be released with ipywidgets 8.
Title assignment examples for Tab and Accordion from readthedocs are not working
@CatChenal - make sure you are looking at the stable docs for ipywidgets 7.x. The development docs are for ipywidgets 8.
Most helpful comment
+1. It's bothered me for a long time that we have get_title and set_title.
Additionally, looking at the code, it's weird that titles is a dictionary indexed with integers, instead of just a tuple corresponding to the children. I think we could expose a tuple interface to users (along with constructor attribute) in a backwards-compatible way (i.e., changes to the tuple would change the dict that is synced), and we could eliminate the dict in 8.0.