IPython's builtin Widgets

IPython 2.0 will ship with a basic set of Widgets. These Widget are designed to be lightweight so that users can quickly build interactive UIs for working with data. This is not Qt!


In [1]:
from IPython.html import widgets
from IPython.display import display, clear_output

Here is a list of the Widgets that IPython 2.0 will ship with:


In [2]:
[widget for widget in dir(widgets) if widget.endswith('Widget')]


Out[2]:
['AccordionWidget',
 'BoundedFloatTextWidget',
 'BoundedIntTextWidget',
 'ButtonWidget',
 'CheckboxWidget',
 'ContainerWidget',
 'DOMWidget',
 'DropdownWidget',
 'FloatProgressWidget',
 'FloatSliderWidget',
 'FloatTextWidget',
 'HTMLWidget',
 'ImageWidget',
 'IntProgressWidget',
 'IntSliderWidget',
 'IntTextWidget',
 'LatexWidget',
 'PopupWidget',
 'RadioButtonsWidget',
 'SelectWidget',
 'TabWidget',
 'TextWidget',
 'TextareaWidget',
 'ToggleButtonWidget',
 'ToggleButtonsWidget',
 'Widget']

We are trying to cover the basic set of widgets that are needed as building blocks for more complicated user interfaces. In the long run, we plan on keeping the number of widgets that IPython ships relatively small. We will encourage the larger community to build and distribute more sophisticated custom widgets as separate projects.

Widget basics

Here is a slider widget whose value is a floating point number. Widgets have sensible default values:


In [3]:
w = widgets.FloatSliderWidget()

Widgets can be displayed using IPython's display function:


In [4]:
display(w)

Or by returning a widget as the result of an expression:


In [5]:
w

From an MVC perspective, Python widgets are models. In reality, these models are instantiated automatically in both Python and JavaScript and the two sides are fully synchronized. When displayed, JavaScript based views (through Backbone.js) are created for the models. Multiple views of the same model will be synchronized.

The models have strongly typed data attributes. For example, slider widgets have a .value attribute that is a float and can be used to get or set the slider's value:


In [6]:
w.value


Out[6]:
0.0

In [7]:
w.value = 100.0

All widgets have a .close() method that removes their views from the page and cleans up the synchronization layer:


In [8]:
w.close()

The .keys attributes lists all of the attributes that will be synchronized with JavaScript:


In [9]:
w.keys


Out[9]:
['_view_name',
 'orientation',
 'min',
 'max',
 '_css',
 'value',
 'readout',
 'disabled',
 'visible',
 'step',
 'description']

Events

It is possible to define event handlers on both the JavaScript and Python sides. On the Python side, these handlers are registered using the .on_trait_change() method. On the JavaScript side Backbone.js or jQuery can be used.

This example also shows how attributes (min, max, step) can be set in the constructor.


In [10]:
def on_value_change(name, value):
    print(value)

int_range = widgets.IntSliderWidget(min=0, max=10, step=2)
int_range.on_trait_change(on_value_change, 'value')
display(int_range)

Some widgets have specialized events, such as the on_click event of the ButtonWidget:


In [11]:
def click_handler(widget):
    print "clicked"

b = widgets.ButtonWidget(description='Click Me!')
b.on_click(click_handler)
display(b)

Containers and visibility

IPython widgets use an explicit, container based layout approach. The CSS Flexible Box Model provides the actual layout on the page. We offer a range of different containers, from simple containers, to tabs, etc.

All widgets have a .visible attribute that can be used to hide and show the widget on the page.


In [12]:
form = widgets.ContainerWidget()
first = widgets.TextWidget(description="First Name:")
last = widgets.TextWidget(description="Last Name:")

student = widgets.CheckboxWidget(description="Student:", value=False)
school_info = widgets.ContainerWidget(visible=False, children=[
    widgets.TextWidget(description="School:"),
    widgets.IntTextWidget(description="Grade:", min=0, max=12)
    ])

state = widgets.DropdownWidget(description='State:', values=['CA', 'OR', 'WA'])
form.children = [first, last, student, school_info, state]
display(form)

def on_student_toggle(name, value):
    if value:
        school_info.visible = True
    else:
        school_info.visible = False
student.on_trait_change(on_student_toggle, 'value')

In [13]:
state.value


Out[13]:
'CA'

Layout and CSS

Some widgets, such as the various slider ones, have layout options.

Most widgets are also subclasses of DOMWidget and offer methods for managing the CSS of the elements on the page:

  • add_class
  • remove_class
  • set_css

In this case we create vertically oriented sliders using the Flexible Box Model.


In [14]:
container = widgets.ContainerWidget()
children = []
for i in range(15):
    w = widgets.FloatSliderWidget(orientation='vertical', description=str(i+1), value=50.0)
    children.append(w)
container.children = children
display(container)
container.remove_class('vbox')
container.add_class('hbox')
container.set_css('background','lightblue')
container.set_css('border-radius', '10px')

In [14]:


In [ ]: