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]:
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.
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]:
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]:
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)
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]:
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 [ ]: