Widget Events.ipynb
383 lines
| 9.4 KiB
| text/plain
|
TextLexer
Jonathan Frederic
|
r14323 | { | ||
Min RK
|
r18669 | "cells": [ | ||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": { | ||||
"slideshow": { | ||||
"slide_type": "slide" | ||||
} | ||||
}, | ||||
"source": [ | ||||
"# Widget Events" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"## Special events" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"from __future__ import print_function" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"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." | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"from IPython.html import widgets\n", | ||||
"print(widgets.Button.on_click.__doc__)" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": { | ||||
"slideshow": { | ||||
"slide_type": "slide" | ||||
} | ||||
}, | ||||
"source": [ | ||||
"### Example" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"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." | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"from IPython.display import display\n", | ||||
"button = widgets.Button(description=\"Click Me!\")\n", | ||||
"display(button)\n", | ||||
"\n", | ||||
"def on_button_clicked(b):\n", | ||||
" print(\"Button clicked.\")\n", | ||||
"\n", | ||||
"button.on_click(on_button_clicked)" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": { | ||||
"slideshow": { | ||||
"slide_type": "slide" | ||||
} | ||||
}, | ||||
"source": [ | ||||
"### on_sumbit" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"The **`Text`** also has a special **`on_submit` event**. The `on_submit` event **fires when the user hits return**." | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"text = widgets.Text()\n", | ||||
"display(text)\n", | ||||
"\n", | ||||
"def handle_submit(sender):\n", | ||||
" print(text.value)\n", | ||||
"\n", | ||||
"text.on_submit(handle_submit)" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": { | ||||
"slideshow": { | ||||
"slide_type": "slide" | ||||
} | ||||
}, | ||||
"source": [ | ||||
"## Traitlet events" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"**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." | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"print(widgets.Widget.on_trait_change.__doc__)" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": { | ||||
"slideshow": { | ||||
"slide_type": "slide" | ||||
} | ||||
}, | ||||
"source": [ | ||||
"### Signatures" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"Mentioned in the doc string, the callback registered can have **4 possible signatures**:\n", | ||||
"\n", | ||||
"- callback()\n", | ||||
"- callback(trait_name)\n", | ||||
"- callback(trait_name, new_value)\n", | ||||
"- callback(trait_name, old_value, new_value)\n", | ||||
"\n", | ||||
"Using this method, an example of how to output an `IntSlider`'s value as it is changed can be seen below." | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"int_range = widgets.IntSlider()\n", | ||||
"display(int_range)\n", | ||||
"\n", | ||||
"def on_value_change(name, value):\n", | ||||
" print(value)\n", | ||||
"\n", | ||||
"int_range.on_trait_change(on_value_change, 'value')" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
Jason Grout
|
r19202 | "# Linking Widgets" | ||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"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. \n", | ||||
"\n", | ||||
"The first method is to use the `link` and `directional_link` functions from the `traitlets` module. " | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"## Linking traitlets attributes from the server side" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"from IPython.utils import traitlets" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"caption = widgets.Latex(value = 'The values of slider1, slider2 and slider3 are synchronized')\n", | ||||
"sliders1, slider2, slider3 = widgets.IntSlider(description='Slider 1'),\\\n", | ||||
" widgets.IntSlider(description='Slider 2'),\\\n", | ||||
" widgets.IntSlider(description='Slider 3')\n", | ||||
"l = traitlets.link((sliders1, 'value'), (slider2, 'value'), (slider3, 'value'))\n", | ||||
"display(caption, sliders1, slider2, slider3)" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"caption = widgets.Latex(value = 'Changes in source values are reflected in target1 and target2')\n", | ||||
"source, target1, target2 = widgets.IntSlider(description='Source'),\\\n", | ||||
" widgets.IntSlider(description='Target 1'),\\\n", | ||||
" widgets.IntSlider(description='Target 2')\n", | ||||
"traitlets.dlink((source, 'value'), (target1, 'value'), (target2, 'value'))\n", | ||||
"display(caption, source, target1, target2)" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"Function `traitlets.link` returns a `Link` object. The link can be broken by calling the `unlink` method." | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"# l.unlink()" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"## Linking widgets attributes from the client side" | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
"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. " | ||||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"caption = widgets.Latex(value = 'The values of range1, range2 and range3 are synchronized')\n", | ||||
"range1, range2, range3 = widgets.IntSlider(description='Range 1'),\\\n", | ||||
" widgets.IntSlider(description='Range 2'),\\\n", | ||||
" widgets.IntSlider(description='Range 3')\n", | ||||
Gareth Elston
|
r20599 | "l = widgets.jslink((range1, 'value'), (range2, 'value'), (range3, 'value'))\n", | ||
Jason Grout
|
r19202 | "display(caption, range1, range2, range3)" | ||
] | ||||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
"caption = widgets.Latex(value = 'Changes in source_range values are reflected in target_range1 and target_range2')\n", | ||||
"source_range, target_range1, target_range2 = widgets.IntSlider(description='Source range'),\\\n", | ||||
" widgets.IntSlider(description='Target range 1'),\\\n", | ||||
" widgets.IntSlider(description='Target range 2')\n", | ||||
Gareth Elston
|
r20599 | "widgets.jsdlink((source_range, 'value'), (target_range1, 'value'), (target_range2, 'value'))\n", | ||
Jason Grout
|
r19202 | "display(caption, source_range, target_range1, target_range2)" | ||
] | ||||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
Gareth Elston
|
r20620 | "Function `widgets.jslink` returns a `Link` widget. The link can be broken by calling the `unlink` method." | ||
Jason Grout
|
r19202 | ] | ||
}, | ||||
{ | ||||
"cell_type": "code", | ||||
"execution_count": null, | ||||
"metadata": { | ||||
"collapsed": false | ||||
}, | ||||
"outputs": [], | ||||
"source": [ | ||||
Jason Grout
|
r19390 | "# l.unlink()" | ||
Jason Grout
|
r19202 | ] | ||
}, | ||||
{ | ||||
"cell_type": "markdown", | ||||
"metadata": {}, | ||||
"source": [ | ||||
Min RK
|
r18669 | "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)" | ||
] | ||||
} | ||||
], | ||||
Jonathan Frederic
|
r14323 | "metadata": { | ||
Jonathan Frederic
|
r14342 | "cell_tags": [ | ||
[ | ||||
"<None>", | ||||
null | ||||
] | ||||
], | ||||
Jonathan Frederic
|
r17726 | "kernelspec": { | ||
Min RK
|
r20278 | "display_name": "Python 3", | ||
"language": "python", | ||||
"name": "python3" | ||||
Jonathan Frederic
|
r17726 | }, | ||
Jason Grout
|
r19390 | "language_info": { | ||
"codemirror_mode": { | ||||
"name": "ipython", | ||||
Min RK
|
r20278 | "version": 3 | ||
Jason Grout
|
r19390 | }, | ||
"file_extension": ".py", | ||||
"mimetype": "text/x-python", | ||||
"name": "python", | ||||
"nbconvert_exporter": "python", | ||||
Min RK
|
r20278 | "pygments_lexer": "ipython3", | ||
"version": "3.4.2" | ||||
} | ||||
Jonathan Frederic
|
r14323 | }, | ||
Min RK
|
r18669 | "nbformat": 4, | ||
"nbformat_minor": 0 | ||||
Min RK
|
r20278 | } | ||