Issue
This Content is from Stack Overflow. Question asked by nvaytet
I am trying to create an object that behaves like an ipywidget
, but contains two sliders instead of a single one. This object would have a value
property that would return a dict
of values (one entry for each slider).
I would also like this widget to be embeddable inside other container widgets (VBox
, HBox
).
I can create a custom class which contains two sliders, and looks like a widget by giving it the proper _repr_mimebundle_
:
import ipywidgets as ipw
class SliderWidget:
def __init__(self):
self._sliders = {name: ipw.IntSlider(description=name) for name in ('slider1', 'slider2')}
def observe(self, callback, **kwargs):
for sl in self._sliders.values():
sl.observe(callback, **kwargs)
@property
def value(self):
return {name: sl.value for name, sl in self._sliders.items()}
@value.setter
def value(self, val):
for name, v in val.items():
self._sliders[name].value = v
def _repr_mimebundle_(self, include=None, exclude=None):
return ipw.VBox(list(self._sliders.values()))._repr_mimebundle_(include=include, exclude=exclude)
which then looks as it should
and also works well with the observe
method
def func(change):
print(change)
sw.observe(func, names='value')
However, it cannot be embedded in other widgets, because it is not a Widget itself:
ipw.HBox([sw, sw])
TraitError: The 'children' trait of a HBox instance contains an Instance of a TypedTuple which expected a Widget, not the SliderWidget at '0x7fbb10757b20'.
To fix this, I have tried to inherit from VBox
, which works nicely
class SliderWidget(ipw.VBox):
def __init__(self):
self._sliders = {name: ipw.IntSlider(description=name) for name in ('slider1', 'slider2')}
super().__init__(list(self._sliders.values()))
# def observe(self, callback, **kwargs):
# for sl in self._sliders.values():
# sl.observe(callback, **kwargs)
@property
def value(self):
return {name: sl.value for name, sl in self._sliders.items()}
@value.setter
def value(self, val):
for name, v in val.items():
self._sliders[name].value = v
and can be embedded inside other widgets
but unfortunately, I cannot seem to get the observe
to work.
If I uncomment the overriding of the observe
method, I get this error upon creating the widget:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [68], in <cell line: 1>()
----> 1 sw = SliderWidget()
2 sw
File ~/software/miniconda3/envs/mini/lib/python3.9/site-packages/traitlets/traitlets.py:1183, in HasDescriptors.__new__(*args, **kwargs)
1181 else:
1182 inst = new_meth(cls, *args, **kwargs)
-> 1183 inst.setup_instance(*args, **kwargs)
1184 return inst
File ~/software/miniconda3/envs/mini/lib/python3.9/site-packages/traitlets/traitlets.py:1224, in HasTraits.setup_instance(*args, **kwargs)
1222 self._trait_validators = {}
1223 self._cross_validation_lock = False
-> 1224 super(HasTraits, self).setup_instance(*args, **kwargs)
File ~/software/miniconda3/envs/mini/lib/python3.9/site-packages/traitlets/traitlets.py:1206, in HasDescriptors.setup_instance(*args, **kwargs)
1204 else:
1205 if isinstance(value, BaseDescriptor):
-> 1206 value.instance_init(self)
File ~/software/miniconda3/envs/mini/lib/python3.9/site-packages/traitlets/traitlets.py:1148, in ObserveHandler.instance_init(self, inst)
1147 def instance_init(self, inst):
-> 1148 inst.observe(self, self.trait_names, type=self.type)
TypeError: observe() takes 2 positional arguments but 3 were given
Solution
This question is not yet answered, be the first one who answer using the comment. Later the confirmed answer will be published as the solution.
This Question and Answer are collected from stackoverflow and tested by JTuto community, is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.