jupyter-widgets / ipywidgets

Interactive Widgets for the Jupyter Notebook
https://ipywidgets.readthedocs.io
BSD 3-Clause "New" or "Revised" License
3.13k stars 950 forks source link

Overriding _ipython_display_ for widgets in a Box #2274

Open andymcarter opened 5 years ago

andymcarter commented 5 years ago

I have been subclassing the basic ipywidgets to develop notebook GUIs, and have been trying to 'wrap' a basic widget with a HTML label to the left (for consistent layouts). I'm aware there is a description kwarg but I often want to create a single class which contains multiple widgets (e.g. a start and end date picker), but just has a single label.

I understand _ipython_display_ can be overrided to change how a widget is displayed (following the example here).

This works fine when calling a widget to display directly (see below):

import ipywidgets as ipyw

label_layout = ipyw.Layout(width='100px')

class WrappedToggles(ipyw.ToggleButtons):

    def __init__(self):
        layout = ipyw.Layout(width='400px')
        super().__init__(options=['1','2'], layout=layout)

    def _ipython_display_(self, **kwargs):
        label = 'Label:'
        box_label = ipyw.HTML(value=label, layout=label_layout)
        children = (box_label, self)
        ipyw.HBox(children=children)._ipython_display_()

WrappedToggles()

image

However, if I try to add these widgets to a Box, the _ipython_display_ method is not respected, and the widget displays as if it is the simple inherited widget (in this case, the Togglebuttons).

children = [WrappedToggles(), WrappedToggles()]
ipyw.VBox(children=children)

image

Can I get the custom _ipython_display_ behaviour when combining these 'wrapped' widgets into a dashboard Box?

ipywidgets version 7.4.2 IPython 7.1.1

maartenbreddels commented 5 years ago

I don't think this should be supported, those are two different worlds, the display mechanism (out of the ipywidget realm) and the widgets. I think a better solution would be to inherit from HBox, and add the children. Would that work for you?

SylvainCorlay commented 5 years ago

The base _ipython_display_ for widgets will be removed in the next major version and we will fully rely on _repr_mimebundle_.

andymcarter commented 5 years ago

Understood Maarten, thanks. Hadn't appreciated that _ipython_display_ wasn't a specific thing for widgets.

I guess I should inherit from HBox, create HTML and ToggleButtons widgets in the __init__, then pass them as children to super().__init__. Then I could override the required methods on this class to delegate to the ToggleButtons (like get_interact_value()). Sounds like a more compositional approach would be beneficial here?

maartenbreddels commented 5 years ago

Yes, I think that would be a better approach. If you want it to behave like a ToggleButtons, you could copy its traits (removing .tag(sync=True) and link the traits together.

vidartf commented 5 years ago

Xref #1811.