#!/usr/bin/env python # coding: utf-8 # [Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb) # # Widget Events # ## Special events # In[ ]: from __future__ import print_function # The `Button` is not used to represent a data type. Instead the button widget is used to **handle mouse clicks**. The **`on_click` method** of the `Button` can be used to register function to be called when the button is clicked. The doc string of the `on_click` can be seen below. # In[ ]: from IPython.html import widgets print(widgets.Button.on_click.__doc__) # ### Example # Since button clicks are **stateless**, they are **transmitted from the front-end to the back-end using custom messages**. By using the `on_click` method, a button that prints a message when it has been clicked is shown below. # In[ ]: from IPython.display import display button = widgets.Button(description="Click Me!") display(button) def on_button_clicked(b): print("Button clicked.") button.on_click(on_button_clicked) # ### on_sumbit # The **`Text`** also has a special **`on_submit` event**. The `on_submit` event **fires when the user hits return**. # In[ ]: text = widgets.Text() display(text) def handle_submit(sender): print(text.value) text.on_submit(handle_submit) # ## Traitlet events # **Widget properties are IPython traitlets** and **traitlets are eventful**. To handle changes, the **`on_trait_change` method** of the widget can be used to **register a callback**. The doc string for `on_trait_change` can be seen below. # In[ ]: print(widgets.Widget.on_trait_change.__doc__) # ### Signatures # Mentioned in the doc string, the callback registered can have **4 possible signatures**: # # - callback() # - callback(trait_name) # - callback(trait_name, new_value) # - callback(trait_name, old_value, new_value) # # Using this method, an example of how to output an `IntSlider`'s value as it is changed can be seen below. # In[ ]: int_range = widgets.IntSlider() display(int_range) def on_value_change(name, value): print(value) int_range.on_trait_change(on_value_change, 'value') # # Linking Widgets # Often, you may want to simply link widget attributes together. Synchronization of attributes can be done in a simpler way than by using bare traitlets events. # # The first method is to use the `link` and `directional_link` functions from the `traitlets` module. # ## Linking traitlets attributes from the server side # In[ ]: from IPython.utils import traitlets # In[ ]: caption = widgets.Latex(value = 'The values of slider1, slider2 and slider3 are synchronized') sliders1, slider2, slider3 = widgets.IntSlider(description='Slider 1'),\ widgets.IntSlider(description='Slider 2'),\ widgets.IntSlider(description='Slider 3') l = traitlets.link((sliders1, 'value'), (slider2, 'value'), (slider3, 'value')) display(caption, sliders1, slider2, slider3) # In[ ]: caption = widgets.Latex(value = 'Changes in source values are reflected in target1 and target2') source, target1, target2 = widgets.IntSlider(description='Source'),\ widgets.IntSlider(description='Target 1'),\ widgets.IntSlider(description='Target 2') traitlets.dlink((source, 'value'), (target1, 'value'), (target2, 'value')) display(caption, source, target1, target2) # Function `traitlets.link` returns a `Link` object. The link can be broken by calling the `unlink` method. # In[ ]: # l.unlink() # ## Linking widgets attributes from the client side # When synchronizing traitlets attributes, you may experience a lag because of the latency dues to the rountrip to the server side. You can also directly link widgets attributes, either in a unidirectional or a bidirectional fashion using the link widgets. # In[ ]: caption = widgets.Latex(value = 'The values of range1, range2 and range3 are synchronized') range1, range2, range3 = widgets.IntSlider(description='Range 1'),\ widgets.IntSlider(description='Range 2'),\ widgets.IntSlider(description='Range 3') l = widgets.jslink((range1, 'value'), (range2, 'value'), (range3, 'value')) display(caption, range1, range2, range3) # In[ ]: caption = widgets.Latex(value = 'Changes in source_range values are reflected in target_range1 and target_range2') source_range, target_range1, target_range2 = widgets.IntSlider(description='Source range'),\ widgets.IntSlider(description='Target range 1'),\ widgets.IntSlider(description='Target range 2') widgets.jsdlink((source_range, 'value'), (target_range1, 'value'), (target_range2, 'value')) display(caption, source_range, target_range1, target_range2) # Function `widgets.jslink` returns a `Link` widget. The link can be broken by calling the `unlink` method. # In[ ]: # l.unlink() # [Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)