Reputation: 16455
I'm trying to figure out how to link the value of a counter controlled by button widgets to the value of a slider widget.
The goal here is use ipython widgets to create a simple "vcr-like" interface with three widgets: an IntSlider
and two Button
s that increment a counter and decrement a counter. This is what I've got:
import ipywidgets as widgets
from functools import partial
from IPython.display import display
import traitlets
class Counter:
def __init__(self, initial=0):
self.value = initial
def increment(self, amount=1):
self.value += amount
return self.value
def button_plus(counter, w):
counter.increment(+1)
def button_minus(counter, w):
counter.increment(-1)
counter = Counter()
# 1 step forward button
wplus = widgets.Button(description='>')
wplus.on_click(partial(button_plus, counter))
# 1 step backward button
wminus = widgets.Button(description='<')
wminus.on_click(partial(button_minus, counter))
# integer slider
wpick = widgets.IntSlider(value=0,min=0,max=10,step=1,description="time step")
display(wminus, wpick, wplus)
print(counter.value)
print(wpick.value)
and here's a screen grab where I've moved the IntSlider to 1 and clicked twice on the increment button:
I'd obviously like there to be a single integer value being controlled by and be in sync with all 3 widgets.
I read about widget linking but I don't see how to do this since my button widgets don't have a value -- the counter object has the value I want to link.
This doesn't work:
l = traitlets.link((counter, 'value'), (wpick, 'value'))
because counter
is not HasTraits
.
How can I get counter.value
to be linked to wpick.value
so that clicking on one of the buttons will adjust the int on the slider?
Upvotes: 3
Views: 4572
Reputation: 1345
Following this guide, you need the Counter
class to inheret from the DOMWidget
class like this:
from traitlets import CInt, link
class Counter(widgets.DOMWidget):
value = CInt(0, sync=True)
You can then define your counter
widget and button callback methods:
counter = Counter()
def button_plus(name):
counter.value += 1 if counter.value < 10 else 0
def button_minus(name):
counter.value -= 1 if counter.value > 0 else 0
link the slider
and counter
widgets:
link((wpick, 'value'), (counter, 'value'))
and register the events on the buttons:
wplus.on_click(button_plus)
wminus.on_click(button_minus)
Clicking the buttons will now in/decrease the value of the counter.
Upvotes: 4