diff --git a/GUI/.ipynb_checkpoints/1 - Interact-checkpoint.ipynb b/GUI/.ipynb_checkpoints/1 - Interact-checkpoint.ipynb new file mode 100644 index 0000000..a2d1a77 --- /dev/null +++ b/GUI/.ipynb_checkpoints/1 - Interact-checkpoint.ipynb @@ -0,0 +1,835 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using Interact\n", + "\n", + "In this lecture we will begin to learn about creating dashboard-type GUI with iPython widgets!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `interact` function (`ipywidgets.interact`) automatically creates user interface (UI) controls for exploring code and data interactively. It is the easiest way to get started using IPython's widgets." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from __future__ import print_function\n", + "from ipywidgets import interact, interactive, fixed\n", + "import ipywidgets as widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Please Note! The widgets in this notebook won't show up on NbViewer or GitHub renderings . To view the widgets and interact with them, you will need to download this notebook and run it with a Jupyter Notebook server.\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic `interact`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At the most basic level, `interact` autogenerates UI controls for function arguments, and then calls the function with those arguments when you manipulate the controls interactively. To use `interact`, you need to define a function that you want to explore. Here is a function that prints its only argument `x`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def f(x):\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you pass this function as the first argument to `interact` along with an integer keyword argument (`x=10`), a slider is generated and bound to the function parameter." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "-2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=10);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you move the slider, the function is called, which prints the current value of `x`.\n", + "\n", + "If you pass `True` or `False`, `interact` will generate a checkbox:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=True);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you pass a string, `interact` will generate a text area." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "u'Hello!!!'" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x='Hi there!');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`interact` can also be used as a decorator. This allows you to define a function and interact with it in a single shot. As this example shows, `interact` also works with functions that have multiple arguments." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(True, 0.3)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@interact(x=True, y=1.0)\n", + "def g(x, y):\n", + " return (x, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fixing arguments using `fixed`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are times when you may want to explore a function using `interact`, but fix one or more of its arguments to specific values. This can be accomplished by wrapping values with the `fixed` function." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def h(p, q):\n", + " return (p, q)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we call `interact`, we pass `fixed(20)` for q to hold it fixed at a value of `20`." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0, 20)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(h, p=5, q=fixed(20));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that a slider is only produced for `p` as the value of `q` is fixed." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Widget abbreviations" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you pass an integer-valued keyword argument of `10` (`x=10`) to `interact`, it generates an integer-valued slider control with a range of $[-10,+3\\times10]$. In this case, `10` is an *abbreviation* for an actual slider widget:\n", + "\n", + "```python\n", + "IntSlider(min=-10,max=30,step=1,value=10)\n", + "```\n", + "\n", + "In fact, we can get the same result if we pass this `IntSlider` as the keyword argument for `x`:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "20" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=widgets.IntSlider(min=-10,max=30,step=1,value=10));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This examples clarifies how `interact` proceses its keyword arguments:\n", + "\n", + "1. If the keyword argument is a `Widget` instance with a `value` attribute, that widget is used. Any widget with a `value` attribute can be used, even custom ones.\n", + "2. Otherwise, the value is treated as a *widget abbreviation* that is converted to a widget before it is used.\n", + "\n", + "The following table gives an overview of different widget abbreviations:\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Keyword argumentWidget
`True` or `False`Checkbox
`'Hi there'`Text
`value` or `(min,max)` or `(min,max,step)` if integers are passedIntSlider
`value` or `(min,max)` or `(min,max,step)` if floats are passedFloatSlider
`('orange','apple')` or `{'one':1,'two':2}`Dropdown
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You have seen how the checkbox and textarea widgets work above. Here, more details about the different abbreviations for sliders and dropdowns are given.\n", + "\n", + "If a 2-tuple of integers is passed `(min,max)`, an integer-valued slider is produced with those minimum and maximum values (inclusively). In this case, the default step size of `1` is used." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=(0,4));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If a 3-tuple of integers is passed `(min,max,step)`, the step size can also be set." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=(0,8,2));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A float-valued slider is produced if the elements of the tuples are floats. Here the minimum is `0.0`, the maximum is `10.0` and step size is `0.1` (the default)." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=(0.0,10.0));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The step size can be changed by passing a third element in the tuple." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4.98" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=(0.0,10.0,0.01));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For both integer and float-valued sliders, you can pick the initial value of the widget by passing a default keyword argument to the underlying Python function. Here we set the initial value of a float slider to `5.5`." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "5.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@interact(x=(0.0,20.0,0.5))\n", + "def h(x=5.5):\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dropdown menus are constructed by passing a tuple of strings. In this case, the strings are both used as the names in the dropdown menu UI and passed to the underlying Python function." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "u'apples'" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=('apples','oranges'));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want a dropdown menu that passes non-string values to the Python function, you can pass a dictionary. The keys in the dictionary are used for the names in the dropdown menu UI and the values are the arguments that are passed to the underlying Python function." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "20" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x={'one': 10, 'two': 20});" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using function annotations with `interact`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are using Python 3, you can also specify widget abbreviations using [function annotations](https://docs.python.org/3/tutorial/controlflow.html#function-annotations).\n", + "\n", + "Define a function with a checkbox widget abbreviation for the argument `x`." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m def f(x:True): # python 3 only\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "def f(x:True): # python 3 only\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, because the widget abbreviation has already been defined, you can call `interact` with a single argument." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "interact(f);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are running Python 2, function annotations can be defined using the `@annotate` function." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.utils.py3compat import annotate" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "@annotate(x=True)\n", + "def f(x):\n", + " return x" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## interactive" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to `interact`, IPython provides another function, `interactive`, that is useful when you want to reuse the widgets that are produced or access the data that is bound to the UI controls." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is a function that returns the sum of its two arguments." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def f(a, b):\n", + " return a+b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Unlike `interact`, `interactive` returns a `Widget` instance rather than immediately displaying the widget." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w = interactive(f, a=10, b=20)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The widget is a `Box`, which is a container for other widgets." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "ipywidgets.widgets.widget_box.Box" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The children of the `Box` are two integer-valued sliders produced by the widget abbreviations above." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(,\n", + " )" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w.children" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To actually display the widgets, you can use IPython's `display` function." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "65" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display\n", + "display(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At this point, the UI controls work just like they would if `interact` had been used. You can manipulate them interactively and the function will be called. However, the widget instance returned by `interactive` also give you access to the current keyword arguments and return value of the underlying Python function.\n", + "\n", + "Here are the current keyword arguments. If you rerun this cell after manipulating the sliders, the values will have changed." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a': 16, 'b': 49}" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w.kwargs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is the current return value of the function." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "65" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w.result" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/GUI/.ipynb_checkpoints/2 - Widget Basics-checkpoint.ipynb b/GUI/.ipynb_checkpoints/2 - Widget Basics-checkpoint.ipynb new file mode 100644 index 0000000..05e2862 --- /dev/null +++ b/GUI/.ipynb_checkpoints/2 - Widget Basics-checkpoint.ipynb @@ -0,0 +1,436 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Widget Basics\n", + "\n", + "In this lecture we will continue to build off our understanding of **interact** and **interactive** to begin using full widgets!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What are widgets?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Widgets are eventful python objects that have a representation in the browser, often as a control like a slider, textbox, etc." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What can they be used for?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "You can use widgets to build **interactive GUIs** for your notebooks. \n", + "You can also use widgets to **synchronize stateful and stateless information** between Python and JavaScript." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using widgets " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "To use the widget framework, you need to import `ipywidgets`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ipywidgets import *" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### repr" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Widgets have their own display `repr` which allows them to be displayed using IPython's display framework. Constructing and returning an `IntSlider` automatically displays the widget (as seen below). Widgets are displayed inside the widget area, which sits between the code cell and output. You can hide all of the widgets in the widget area by clicking the grey *x* in the margin." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "IntSlider()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### display()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also explicitly display the widget using `display(...)`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "w = IntSlider()\n", + "display(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Multiple display() calls" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you display the same widget twice, the displayed instances in the front-end will remain in sync with each other. Try dragging the slider below and watch the slider above." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Why does displaying the same widget twice work?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Widgets are represented in the back-end by a single object. Each time a widget is displayed, a new representation of that same object is created in the front-end. These representations are called views.\n", + "\n", + "![Kernel & front-end diagram](images/WidgetModelView.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Closing widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can close a widget by calling its `close()` method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Widget properties" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "All of the IPython widgets share a similar naming scheme. To read the value of a widget, you can query its `value` property." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w = IntSlider()\n", + "display(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.value" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, to set a widget's value, you can set its `value` property." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.value = 100" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Keys" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to `value`, most widgets share `keys`, `description`, `disabled`, and `visible`. To see the entire list of synchronized, stateful properties of any specific widget, you can query the `keys` property." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.keys" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Shorthand for setting the initial values of widget properties" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "While creating a widget, you can set some or all of the initial values of that widget by defining them as keyword arguments in the widget's constructor (as seen below)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "Text(value='Hello World!', disabled=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Linking two similar widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "If you need to display the same value two different ways, you'll have to use two different widgets. Instead of attempting to manually synchronize the values of the two widgets, you can use the `traitlet` `link` function to link two properties together. Below, the values of two widgets are linked together." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from traitlets import link\n", + "a = FloatText()\n", + "b = FloatSlider()\n", + "display(a,b)\n", + "\n", + "mylink = link((a, 'value'), (b, 'value'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Unlinking widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Unlinking the widgets is simple. All you have to do is call `.unlink` on the link object. Try changing one of the widgets above after unlinking to see that they can be independently changed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mylink.unlink()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Index](Index.ipynb) - [Next](Widget List.ipynb)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/GUI/.ipynb_checkpoints/Interact-checkpoint.ipynb b/GUI/.ipynb_checkpoints/Interact-checkpoint.ipynb deleted file mode 100644 index e5b1a1c..0000000 --- a/GUI/.ipynb_checkpoints/Interact-checkpoint.ipynb +++ /dev/null @@ -1,95 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Interact\n", - "\n", - "Let's get started with widgets in the Jupyter Notebook! We'll start with **interact**. **interact** is able to *auto-generate* UI controls for function arguments, and then calls the function with those arguments." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "from ipywidgets import interact, interactive, fixed\n", - "import ipywidgets as widgets" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Basics" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def f(x):\n", - " return x" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "6" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "interact(f,x=10)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 2", - "language": "python", - "name": "python2" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.10" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/GUI/.ipynb_checkpoints/Widget Styling-checkpoint.ipynb b/GUI/.ipynb_checkpoints/Widget Styling-checkpoint.ipynb new file mode 100644 index 0000000..829d3c1 --- /dev/null +++ b/GUI/.ipynb_checkpoints/Widget Styling-checkpoint.ipynb @@ -0,0 +1,564 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Index](Index.ipynb) - [Back](Widget Events.ipynb) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%%html\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import ipywidgets as widgets\n", + "from IPython.display import display" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Widget Styling" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic styling" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The widgets distributed with IPython can be styled by setting the following traits:\n", + "\n", + "- width \n", + "- height \n", + "- background_color \n", + "- border_color \n", + "- border_width \n", + "- border_style \n", + "- font_style \n", + "- font_weight \n", + "- font_size \n", + "- font_family \n", + "\n", + "The example below shows how a `Button` widget can be styled:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "button = widgets.Button(\n", + " description='Hello World!',\n", + " width=100, # Integers are interpreted as pixel measurements.\n", + " height='2em', # em is valid HTML unit of measurement.\n", + " color='lime', # Colors can be set by name,\n", + " background_color='#0022FF', # and also by color code.\n", + " border_color='red')\n", + "display(button)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Parent/child relationships" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display widget A inside widget B, widget A must be a child of widget B. Widgets that can contain other widgets have a `children` attribute. This attribute can be set via a keyword argument in the widget's constructor or after construction. Calling display on an object with children automatically displays the children." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "\n", + "float_range = widgets.FloatSlider()\n", + "string = widgets.Text(value='hi')\n", + "container = widgets.Box(children=[float_range, string])\n", + "\n", + "container.border_color = 'red'\n", + "container.border_style = 'dotted'\n", + "container.border_width = 3\n", + "display(container) # Displays the `container` and all of it's children." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### After the parent is displayed" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Children can be added to parents after the parent has been displayed. The parent is responsible for rendering its children." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "container = widgets.Box()\n", + "container.border_color = 'red'\n", + "container.border_style = 'dotted'\n", + "container.border_width = 3\n", + "display(container)\n", + "\n", + "int_range = widgets.IntSlider()\n", + "container.children=[int_range]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Fancy boxes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you need to display a more complicated set of widgets, there are specialized containers that you can use. To display multiple sets of widgets, you can use an `Accordion` or a `Tab` in combination with one `Box` per set of widgets (as seen below). The \"pages\" of these widgets are their children. To set the titles of the pages, use `set_title`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Accordion" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "name1 = widgets.Text(description='Location:')\n", + "zip1 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n", + "page1 = widgets.Box(children=[name1, zip1])\n", + "\n", + "name2 = widgets.Text(description='Location:')\n", + "zip2 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n", + "page2 = widgets.Box(children=[name2, zip2])\n", + "\n", + "accord = widgets.Accordion(children=[page1, page2], width=400)\n", + "display(accord)\n", + "\n", + "accord.set_title(0, 'From')\n", + "accord.set_title(1, 'To')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### TabWidget" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "name = widgets.Text(description='Name:', padding=4)\n", + "color = widgets.Dropdown(description='Color:', padding=4, options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n", + "page1 = widgets.Box(children=[name, color], padding=4)\n", + "\n", + "age = widgets.IntSlider(description='Age:', padding=4, min=0, max=120, value=50)\n", + "gender = widgets.RadioButtons(description='Gender:', padding=4, options=['male', 'female'])\n", + "page2 = widgets.Box(children=[age, gender], padding=4)\n", + "\n", + "tabs = widgets.Tab(children=[page1, page2])\n", + "display(tabs)\n", + "\n", + "tabs.set_title(0, 'Name')\n", + "tabs.set_title(1, 'Details')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Alignment" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Most widgets have a `description` attribute, which allows a label for the widget to be defined.\n", + "The label of the widget has a fixed minimum width.\n", + "The text of the label is always right aligned and the widget is left aligned:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(widgets.Text(description=\"a:\"))\n", + "display(widgets.Text(description=\"aa:\"))\n", + "display(widgets.Text(description=\"aaa:\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "If a label is longer than the minimum width, the widget is shifted to the right:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(widgets.Text(description=\"a:\"))\n", + "display(widgets.Text(description=\"aa:\"))\n", + "display(widgets.Text(description=\"aaa:\"))\n", + "display(widgets.Text(description=\"aaaaaaaaaaaaaaaaaa:\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "If a `description` is not set for the widget, the label is not displayed:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(widgets.Text(description=\"a:\"))\n", + "display(widgets.Text(description=\"aa:\"))\n", + "display(widgets.Text(description=\"aaa:\"))\n", + "display(widgets.Text())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Flex boxes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Widgets can be aligned using the `FlexBox`, `HBox`, and `VBox` widgets." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Application to widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Widgets display vertically by default:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "buttons = [widgets.Button(description=str(i)) for i in range(3)]\n", + "display(*buttons)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Using hbox" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To make widgets display horizontally, they can be children of an `HBox` widget." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "container = widgets.HBox(children=buttons)\n", + "display(container)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Visibility" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `visible` property of widgets can be used to hide or show widgets that have already been displayed (as seen below). The `visible` property can be:\n", + "* `True` - the widget is displayed\n", + "* `False` - the widget is hidden, and the empty space where the widget would be is collapsed\n", + "* `None` - the widget is hidden, and the empty space where the widget would be is shown" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w1 = widgets.Latex(value=\"First line\")\n", + "w2 = widgets.Latex(value=\"Second line\")\n", + "w3 = widgets.Latex(value=\"Third line\")\n", + "display(w1, w2, w3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "w2.visible=None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w2.visible=False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w2.visible=True" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Another example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets. Try toggling the student checkbox." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "form = widgets.VBox()\n", + "first = widgets.Text(description=\"First:\")\n", + "last = widgets.Text(description=\"Last:\")\n", + "\n", + "student = widgets.Checkbox(description=\"Student:\", value=False)\n", + "school_info = widgets.VBox(visible=False, children=[\n", + " widgets.Text(description=\"School:\"),\n", + " widgets.IntText(description=\"Grade:\", min=0, max=12)\n", + " ])\n", + "\n", + "pet = widgets.Text(description=\"Pet:\")\n", + "form.children = [first, last, student, school_info, pet]\n", + "display(form)\n", + "\n", + "def on_student_toggle(name, value):\n", + " if value:\n", + " school_info.visible = True\n", + " else:\n", + " school_info.visible = False\n", + "student.on_trait_change(on_student_toggle, 'value')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Index](Index.ipynb) - [Back](Widget Events.ipynb) - [Next](Custom Widget - Hello World.ipynb)" + ] + } + ], + "metadata": { + "cell_tags": [ + [ + "", + null + ] + ], + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/GUI/1 - Interact.ipynb b/GUI/1 - Interact.ipynb new file mode 100644 index 0000000..a2d1a77 --- /dev/null +++ b/GUI/1 - Interact.ipynb @@ -0,0 +1,835 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using Interact\n", + "\n", + "In this lecture we will begin to learn about creating dashboard-type GUI with iPython widgets!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `interact` function (`ipywidgets.interact`) automatically creates user interface (UI) controls for exploring code and data interactively. It is the easiest way to get started using IPython's widgets." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from __future__ import print_function\n", + "from ipywidgets import interact, interactive, fixed\n", + "import ipywidgets as widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "Please Note! The widgets in this notebook won't show up on NbViewer or GitHub renderings . To view the widgets and interact with them, you will need to download this notebook and run it with a Jupyter Notebook server.\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic `interact`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At the most basic level, `interact` autogenerates UI controls for function arguments, and then calls the function with those arguments when you manipulate the controls interactively. To use `interact`, you need to define a function that you want to explore. Here is a function that prints its only argument `x`." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def f(x):\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you pass this function as the first argument to `interact` along with an integer keyword argument (`x=10`), a slider is generated and bound to the function parameter." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "-2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=10);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you move the slider, the function is called, which prints the current value of `x`.\n", + "\n", + "If you pass `True` or `False`, `interact` will generate a checkbox:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=True);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you pass a string, `interact` will generate a text area." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "u'Hello!!!'" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x='Hi there!');" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`interact` can also be used as a decorator. This allows you to define a function and interact with it in a single shot. As this example shows, `interact` also works with functions that have multiple arguments." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(True, 0.3)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@interact(x=True, y=1.0)\n", + "def g(x, y):\n", + " return (x, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fixing arguments using `fixed`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are times when you may want to explore a function using `interact`, but fix one or more of its arguments to specific values. This can be accomplished by wrapping values with the `fixed` function." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def h(p, q):\n", + " return (p, q)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When we call `interact`, we pass `fixed(20)` for q to hold it fixed at a value of `20`." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(0, 20)" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(h, p=5, q=fixed(20));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Notice that a slider is only produced for `p` as the value of `q` is fixed." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Widget abbreviations" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When you pass an integer-valued keyword argument of `10` (`x=10`) to `interact`, it generates an integer-valued slider control with a range of $[-10,+3\\times10]$. In this case, `10` is an *abbreviation* for an actual slider widget:\n", + "\n", + "```python\n", + "IntSlider(min=-10,max=30,step=1,value=10)\n", + "```\n", + "\n", + "In fact, we can get the same result if we pass this `IntSlider` as the keyword argument for `x`:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "20" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=widgets.IntSlider(min=-10,max=30,step=1,value=10));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This examples clarifies how `interact` proceses its keyword arguments:\n", + "\n", + "1. If the keyword argument is a `Widget` instance with a `value` attribute, that widget is used. Any widget with a `value` attribute can be used, even custom ones.\n", + "2. Otherwise, the value is treated as a *widget abbreviation* that is converted to a widget before it is used.\n", + "\n", + "The following table gives an overview of different widget abbreviations:\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Keyword argumentWidget
`True` or `False`Checkbox
`'Hi there'`Text
`value` or `(min,max)` or `(min,max,step)` if integers are passedIntSlider
`value` or `(min,max)` or `(min,max,step)` if floats are passedFloatSlider
`('orange','apple')` or `{'one':1,'two':2}`Dropdown
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You have seen how the checkbox and textarea widgets work above. Here, more details about the different abbreviations for sliders and dropdowns are given.\n", + "\n", + "If a 2-tuple of integers is passed `(min,max)`, an integer-valued slider is produced with those minimum and maximum values (inclusively). In this case, the default step size of `1` is used." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=(0,4));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If a 3-tuple of integers is passed `(min,max,step)`, the step size can also be set." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=(0,8,2));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A float-valued slider is produced if the elements of the tuples are floats. Here the minimum is `0.0`, the maximum is `10.0` and step size is `0.1` (the default)." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "10.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=(0.0,10.0));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The step size can be changed by passing a third element in the tuple." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "4.98" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=(0.0,10.0,0.01));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For both integer and float-valued sliders, you can pick the initial value of the widget by passing a default keyword argument to the underlying Python function. Here we set the initial value of a float slider to `5.5`." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "5.0" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "@interact(x=(0.0,20.0,0.5))\n", + "def h(x=5.5):\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Dropdown menus are constructed by passing a tuple of strings. In this case, the strings are both used as the names in the dropdown menu UI and passed to the underlying Python function." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "u'apples'" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x=('apples','oranges'));" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want a dropdown menu that passes non-string values to the Python function, you can pass a dictionary. The keys in the dictionary are used for the names in the dropdown menu UI and the values are the arguments that are passed to the underlying Python function." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "20" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f, x={'one': 10, 'two': 20});" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using function annotations with `interact`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are using Python 3, you can also specify widget abbreviations using [function annotations](https://docs.python.org/3/tutorial/controlflow.html#function-annotations).\n", + "\n", + "Define a function with a checkbox widget abbreviation for the argument `x`." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "ename": "SyntaxError", + "evalue": "invalid syntax (, line 1)", + "output_type": "error", + "traceback": [ + "\u001b[0;36m File \u001b[0;32m\"\"\u001b[0;36m, line \u001b[0;32m1\u001b[0m\n\u001b[0;31m def f(x:True): # python 3 only\u001b[0m\n\u001b[0m ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid syntax\n" + ] + } + ], + "source": [ + "def f(x:True): # python 3 only\n", + " return x" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Then, because the widget abbreviation has already been defined, you can call `interact` with a single argument." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "interact(f);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you are running Python 2, function annotations can be defined using the `@annotate` function." + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.utils.py3compat import annotate" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "@annotate(x=True)\n", + "def f(x):\n", + " return x" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "interact(f);" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## interactive" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to `interact`, IPython provides another function, `interactive`, that is useful when you want to reuse the widgets that are produced or access the data that is bound to the UI controls." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is a function that returns the sum of its two arguments." + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def f(a, b):\n", + " return a+b" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Unlike `interact`, `interactive` returns a `Widget` instance rather than immediately displaying the widget." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w = interactive(f, a=10, b=20)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The widget is a `Box`, which is a container for other widgets." + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "ipywidgets.widgets.widget_box.Box" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The children of the `Box` are two integer-valued sliders produced by the widget abbreviations above." + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "(,\n", + " )" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w.children" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To actually display the widgets, you can use IPython's `display` function." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "65" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from IPython.display import display\n", + "display(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At this point, the UI controls work just like they would if `interact` had been used. You can manipulate them interactively and the function will be called. However, the widget instance returned by `interactive` also give you access to the current keyword arguments and return value of the underlying Python function.\n", + "\n", + "Here are the current keyword arguments. If you rerun this cell after manipulating the sliders, the values will have changed." + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "{'a': 16, 'b': 49}" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w.kwargs" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here is the current return value of the function." + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "65" + ] + }, + "execution_count": 30, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w.result" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/GUI/2 - Widget Basics.ipynb b/GUI/2 - Widget Basics.ipynb new file mode 100644 index 0000000..05e2862 --- /dev/null +++ b/GUI/2 - Widget Basics.ipynb @@ -0,0 +1,436 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Widget Basics\n", + "\n", + "In this lecture we will continue to build off our understanding of **interact** and **interactive** to begin using full widgets!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What are widgets?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Widgets are eventful python objects that have a representation in the browser, often as a control like a slider, textbox, etc." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## What can they be used for?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "You can use widgets to build **interactive GUIs** for your notebooks. \n", + "You can also use widgets to **synchronize stateful and stateless information** between Python and JavaScript." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using widgets " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "To use the widget framework, you need to import `ipywidgets`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from ipywidgets import *" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### repr" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Widgets have their own display `repr` which allows them to be displayed using IPython's display framework. Constructing and returning an `IntSlider` automatically displays the widget (as seen below). Widgets are displayed inside the widget area, which sits between the code cell and output. You can hide all of the widgets in the widget area by clicking the grey *x* in the margin." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "IntSlider()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### display()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also explicitly display the widget using `display(...)`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "w = IntSlider()\n", + "display(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Multiple display() calls" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you display the same widget twice, the displayed instances in the front-end will remain in sync with each other. Try dragging the slider below and watch the slider above." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(w)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Why does displaying the same widget twice work?" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Widgets are represented in the back-end by a single object. Each time a widget is displayed, a new representation of that same object is created in the front-end. These representations are called views.\n", + "\n", + "![Kernel & front-end diagram](images/WidgetModelView.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Closing widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can close a widget by calling its `close()` method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Widget properties" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "All of the IPython widgets share a similar naming scheme. To read the value of a widget, you can query its `value` property." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w = IntSlider()\n", + "display(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.value" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, to set a widget's value, you can set its `value` property." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.value = 100" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Keys" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In addition to `value`, most widgets share `keys`, `description`, `disabled`, and `visible`. To see the entire list of synchronized, stateful properties of any specific widget, you can query the `keys` property." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.keys" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Shorthand for setting the initial values of widget properties" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "While creating a widget, you can set some or all of the initial values of that widget by defining them as keyword arguments in the widget's constructor (as seen below)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "Text(value='Hello World!', disabled=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Linking two similar widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "If you need to display the same value two different ways, you'll have to use two different widgets. Instead of attempting to manually synchronize the values of the two widgets, you can use the `traitlet` `link` function to link two properties together. Below, the values of two widgets are linked together." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from traitlets import link\n", + "a = FloatText()\n", + "b = FloatSlider()\n", + "display(a,b)\n", + "\n", + "mylink = link((a, 'value'), (b, 'value'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Unlinking widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Unlinking the widgets is simple. All you have to do is call `.unlink` on the link object. Try changing one of the widgets above after unlinking to see that they can be independently changed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "mylink.unlink()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Index](Index.ipynb) - [Next](Widget List.ipynb)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/GUI/Interact.ipynb b/GUI/Interact.ipynb deleted file mode 100644 index e5b1a1c..0000000 --- a/GUI/Interact.ipynb +++ /dev/null @@ -1,95 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Interact\n", - "\n", - "Let's get started with widgets in the Jupyter Notebook! We'll start with **interact**. **interact** is able to *auto-generate* UI controls for function arguments, and then calls the function with those arguments." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "from ipywidgets import interact, interactive, fixed\n", - "import ipywidgets as widgets" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Basics" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def f(x):\n", - " return x" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "data": { - "text/plain": [ - "6" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "interact(f,x=10)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 2", - "language": "python", - "name": "python2" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 2 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython2", - "version": "2.7.10" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/GUI/Widget Events.ipynb b/GUI/Widget Events.ipynb new file mode 100644 index 0000000..cd4c3d6 --- /dev/null +++ b/GUI/Widget Events.ipynb @@ -0,0 +1,381 @@ +{ + "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": [ + "import ipywidgets as 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_submit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `Text` widget 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": [ + "# 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. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Linking traitlets attributes from the server side\n", + "\n", + "The first method is to use the `link` and `dlink` functions from the `traitlets` module. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import traitlets" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "caption = widgets.Latex(value = 'The values of slider1 and slider2 are synchronized')\n", + "sliders1, slider2 = widgets.IntSlider(description='Slider 1'),\\\n", + " widgets.IntSlider(description='Slider 2')\n", + "l = traitlets.link((sliders1, 'value'), (slider2, 'value'))\n", + "display(caption, sliders1, slider2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "caption = widgets.Latex(value = 'Changes in source values are reflected in target1')\n", + "source, target1 = widgets.IntSlider(description='Source'),\\\n", + " widgets.IntSlider(description='Target 1')\n", + "dl = traitlets.dlink((source, 'value'), (target1, 'value'))\n", + "display(caption, source, target1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function `traitlets.link` and `traitlets.dlink` return a `Link` or `DLink` object. The link can be broken by calling the `unlink` method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "l.unlink()\n", + "dl.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 due to the roundtrip to the server side. You can also directly link widget attributes in the browser using the link widgets, in either a unidirectional or a bidirectional fashion." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "caption = widgets.Latex(value = 'The values of range1 and range2 are synchronized')\n", + "range1, range2 = widgets.IntSlider(description='Range 1'),\\\n", + " widgets.IntSlider(description='Range 2')\n", + "l = widgets.jslink((range1, 'value'), (range2, 'value'))\n", + "display(caption, range1, range2)" + ] + }, + { + "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')\n", + "source_range, target_range1 = widgets.IntSlider(description='Source range'),\\\n", + " widgets.IntSlider(description='Target range 1')\n", + "dl = widgets.jsdlink((source_range, 'value'), (target_range1, 'value'))\n", + "display(caption, source_range, target_range1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function `widgets.jslink` returns a `Link` widget. The link can be broken by calling the `unlink` method." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "l.unlink()\n", + "dl.unlink()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Index](Index.ipynb) - [Back](Widget List.ipynb) - [Next](Widget Styling.ipynb)" + ] + } + ], + "metadata": { + "cell_tags": [ + [ + "", + null + ] + ], + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.4.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/GUI/Widget List.ipynb b/GUI/Widget List.ipynb new file mode 100644 index 0000000..f517ac2 --- /dev/null +++ b/GUI/Widget List.ipynb @@ -0,0 +1,643 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Widget List" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Complete list" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "For a complete list of the GUI widgets available to you, you can list the registered widget types. `Widget` and `DOMWidget`, not listed below, are base classes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import ipywidgets as widgets\n", + "widgets.Widget.widget_types.values()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Numeric widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are 8 widgets distributed with IPython that are designed to display numeric values. Widgets exist for displaying integers and floats, both bounded and unbounded. The integer widgets share a similar naming scheme to their floating point counterparts. By replacing `Float` with `Int` in the widget name, you can find the Integer equivalent." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### FloatSlider" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.FloatSlider(\n", + " value=7.5,\n", + " min=5.0,\n", + " max=10.0,\n", + " step=0.1,\n", + " description='Test:',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Sliders can also be **displayed vertically**." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.FloatSlider(\n", + " value=7.5,\n", + " min=5.0,\n", + " max=10.0,\n", + " step=0.1,\n", + " description='Test',\n", + " orientation='vertical',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### FloatProgress" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.FloatProgress(\n", + " value=7.5,\n", + " min=5.0,\n", + " max=10.0,\n", + " step=0.1,\n", + " description='Loading:',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### BoundedFloatText" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.BoundedFloatText(\n", + " value=7.5,\n", + " min=5.0,\n", + " max=10.0,\n", + " description='Text:',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### FloatText" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.FloatText(\n", + " value=7.5,\n", + " description='Any:',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Boolean widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are three widgets that are designed to display a boolean value." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ToggleButton" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.ToggleButton(\n", + " description='Click me',\n", + " value=False,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Checkbox" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.Checkbox(\n", + " description='Check me',\n", + " value=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Valid\n", + "\n", + "The valid widget provides a read-only indicator." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "widgets.Valid(\n", + " value=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Selection widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are four widgets that can be used to display single selection lists, and one that can be used to display multiple selection lists. All inherit from the same base class. You can specify the **enumeration of selectable options by passing a list**. You can **also specify the enumeration as a dictionary**, in which case the **keys will be used as the item displayed** in the list and the corresponding **value will be returned** when an item is selected." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Dropdown" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "w = widgets.Dropdown(\n", + " options=['1', '2', '3'],\n", + " value='2',\n", + " description='Number:',\n", + ")\n", + "display(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.value" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following is also valid:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w = widgets.Dropdown(\n", + " options={'One': 1, 'Two': 2, 'Three': 3},\n", + " value=2,\n", + " description='Number:',\n", + ")\n", + "display(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.value" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### RadioButtons" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.RadioButtons(\n", + " description='Pizza topping:',\n", + " options=['pepperoni', 'pineapple', 'anchovies'],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Select" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.Select(\n", + " description='OS:',\n", + " options=['Linux', 'Windows', 'OSX'],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### ToggleButtons" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.ToggleButtons(\n", + " description='Speed:',\n", + " options=['Slow', 'Regular', 'Fast'],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### SelectMultiple\n", + "Multiple values can be selected with shift and/or ctrl (or command) pressed and mouse clicks or arrow keys." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "w = widgets.SelectMultiple(\n", + " description=\"Fruits\",\n", + " options=['Apples', 'Oranges', 'Pears']\n", + ")\n", + "display(w)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w.value" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## String widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are 4 widgets that can be used to display a string value. Of those, the `Text` and `Textarea` widgets accept input. The `Latex` and `HTML` widgets display the string as either Latex or HTML respectively, but do not accept input." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Text" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.Text(\n", + " description='String:',\n", + " value='Hello World',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Textarea" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.Textarea(\n", + " description='String:',\n", + " value='Hello World',\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Latex" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.Latex(\n", + " value=\"$$\\\\frac{n!}{k!(n-k)!} = \\\\binom{n}{k}$$\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### HTML" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.HTML(\n", + " value=\"Hello World\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Button" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "widgets.Button(description='Click me')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Index](Index.ipynb) - [Back](Widget Basics.ipynb) - [Next](Widget Events.ipynb)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.4.3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/GUI/Widget Styling.ipynb b/GUI/Widget Styling.ipynb new file mode 100644 index 0000000..b558012 --- /dev/null +++ b/GUI/Widget Styling.ipynb @@ -0,0 +1,585 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "[Index](Index.ipynb) - [Back](Widget Events.ipynb) " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%%html\n", + "" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import ipywidgets as widgets\n", + "from IPython.display import display" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Widget Styling" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic styling" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The widgets distributed with IPython can be styled by setting the following traits:\n", + "\n", + "- width \n", + "- height \n", + "- background_color \n", + "- border_color \n", + "- border_width \n", + "- border_style \n", + "- font_style \n", + "- font_weight \n", + "- font_size \n", + "- font_family \n", + "\n", + "The example below shows how a `Button` widget can be styled:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "button = widgets.Button(\n", + " description='Hello World!',\n", + " width=100, # Integers are interpreted as pixel measurements.\n", + " height='2em', # em is valid HTML unit of measurement.\n", + " color='lime', # Colors can be set by name,\n", + " background_color='#0022FF', # and also by color code.\n", + " border_color='red')\n", + "display(button)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Parent/child relationships" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To display widget A inside widget B, widget A must be a child of widget B. Widgets that can contain other widgets have a `children` attribute. This attribute can be set via a keyword argument in the widget's constructor or after construction. Calling display on an object with children automatically displays the children." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from IPython.display import display\n", + "\n", + "float_range = widgets.FloatSlider()\n", + "string = widgets.Text(value='hi')\n", + "container = widgets.Box(children=[float_range, string])\n", + "\n", + "container.border_color = 'red'\n", + "container.border_style = 'dotted'\n", + "container.border_width = 3\n", + "display(container) # Displays the `container` and all of it's children." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### After the parent is displayed" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "Children can be added to parents after the parent has been displayed. The parent is responsible for rendering its children." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "container = widgets.Box()\n", + "container.border_color = 'red'\n", + "container.border_style = 'dotted'\n", + "container.border_width = 3\n", + "display(container)\n", + "\n", + "int_range = widgets.IntSlider()\n", + "container.children=[int_range]" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Fancy boxes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you need to display a more complicated set of widgets, there are specialized containers that you can use. To display multiple sets of widgets, you can use an `Accordion` or a `Tab` in combination with one `Box` per set of widgets (as seen below). The \"pages\" of these widgets are their children. To set the titles of the pages, use `set_title`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Accordion" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "name1 = widgets.Text(description='Location:')\n", + "zip1 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n", + "page1 = widgets.Box(children=[name1, zip1])\n", + "\n", + "name2 = widgets.Text(description='Location:')\n", + "zip2 = widgets.BoundedIntText(description='Zip:', min=0, max=99999)\n", + "page2 = widgets.Box(children=[name2, zip2])\n", + "\n", + "accord = widgets.Accordion(children=[page1, page2], width=400)\n", + "display(accord)\n", + "\n", + "accord.set_title(0, 'From')\n", + "accord.set_title(1, 'To')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### TabWidget" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "name = widgets.Text(description='Name:', padding=4)\n", + "color = widgets.Dropdown(description='Color:', padding=4, options=['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'])\n", + "page1 = widgets.Box(children=[name, color], padding=4)\n", + "\n", + "age = widgets.IntSlider(description='Age:', padding=4, min=0, max=120, value=50)\n", + "gender = widgets.RadioButtons(description='Gender:', padding=4, options=['male', 'female'])\n", + "page2 = widgets.Box(children=[age, gender], padding=4)\n", + "\n", + "tabs = widgets.Tab(children=[page1, page2])\n", + "display(tabs)\n", + "\n", + "tabs.set_title(0, 'Name')\n", + "tabs.set_title(1, 'Details')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "# Alignment" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Most widgets have a `description` attribute, which allows a label for the widget to be defined.\n", + "The label of the widget has a fixed minimum width.\n", + "The text of the label is always right aligned and the widget is left aligned:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(widgets.Text(description=\"a:\"))\n", + "display(widgets.Text(description=\"aa:\"))\n", + "display(widgets.Text(description=\"aaa:\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "If a label is longer than the minimum width, the widget is shifted to the right:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(widgets.Text(description=\"a:\"))\n", + "display(widgets.Text(description=\"aa:\"))\n", + "display(widgets.Text(description=\"aaa:\"))\n", + "display(widgets.Text(description=\"aaaaaaaaaaaaaaaaaa:\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "If a `description` is not set for the widget, the label is not displayed:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "display(widgets.Text(description=\"a:\"))\n", + "display(widgets.Text(description=\"aa:\"))\n", + "display(widgets.Text(description=\"aaa:\"))\n", + "display(widgets.Text())" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Flex boxes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Widgets can be aligned using the `FlexBox`, `HBox`, and `VBox` widgets." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Application to widgets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Widgets display vertically by default:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "buttons = [widgets.Button(description=str(i)) for i in range(3)]\n", + "display(*buttons)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Using hbox" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To make widgets display horizontally, they can be children of an `HBox` widget." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "container = widgets.HBox(children=buttons)\n", + "display(container)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "## Visibility" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The `visible` property of widgets can be used to hide or show widgets that have already been displayed (as seen below). The `visible` property can be:\n", + "* `True` - the widget is displayed\n", + "* `False` - the widget is hidden, and the empty space where the widget would be is collapsed\n", + "* `None` - the widget is hidden, and the empty space where the widget would be is shown" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w1 = widgets.Latex(value=\"First line\")\n", + "w2 = widgets.Latex(value=\"Second line\")\n", + "w3 = widgets.Latex(value=\"Third line\")\n", + "display(w1, w2, w3)" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "w2.visible=None" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w2.visible=False" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "w2.visible=True" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "slideshow": { + "slide_type": "slide" + } + }, + "source": [ + "### Another example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the example below, a form is rendered, which conditionally displays widgets depending on the state of other widgets. Try toggling the student checkbox." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "form = widgets.VBox()\n", + "first = widgets.Text(description=\"First:\")\n", + "last = widgets.Text(description=\"Last:\")\n", + "\n", + "student = widgets.Checkbox(description=\"Student:\", value=False)\n", + "school_info = widgets.VBox(visible=False, children=[\n", + " widgets.Text(description=\"School:\"),\n", + " widgets.IntText(description=\"Grade:\", min=0, max=12)\n", + " ])\n", + "\n", + "pet = widgets.Text(description=\"Pet:\")\n", + "form.children = [first, last, student, school_info, pet]\n", + "display(form)\n", + "\n", + "def on_student_toggle(name, value):\n", + " if value:\n", + " school_info.visible = True\n", + " else:\n", + " school_info.visible = False\n", + "student.on_trait_change(on_student_toggle, 'value')\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Conclusion\n", + "\n", + "You should now have an understanding of how to style widgets!" + ] + } + ], + "metadata": { + "cell_tags": [ + [ + "", + null + ] + ], + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +}