Interactive widgets with ipywidgets

Jupyter · Practical · 14 min

Widgets turn a notebook into a small exploratory app: tweak a parameter and see results update without editing code.

ipywidgets provides interactive controls rendered in the notebook and synchronized with Python objects in the kernel. Install it in the kernel environment (pip install ipywidgets); JupyterLab 4 and Notebook 7 support it without extra steps.

The fastest route is interact, which builds controls from a function's arguments:

from ipywidgets import interact
@interact(n=(1, 100), kind=["linear", "log"])
def show(n=10, kind="linear"): ...

A tuple becomes a slider, a list becomes a dropdown, a bool a checkbox, a string a text box. The function reruns every time a value changes; interact_manual adds a Run button for slow functions.

For more control, create widgets directly: widgets.IntSlider(min=0, max=10), Dropdown, Text, Button, Checkbox, DatePicker, combined with layout containers HBox, VBox, Tab and Accordion. Each widget has a value trait. React to changes with:

  • w.observe(callback, names="value"): called with a change dict holding old and new;
  • button.on_click(callback);
  • widgets.link((a, "value"), (b, "value")) to keep two widgets in sync.

Printed output and plots from callbacks should go into a widgets.Output() area, used as a context manager, or they may vanish.

Widgets need a live kernel; in exported HTML they show their last state at best. For shareable apps, consider Voila, Streamlit or Dash.

Example

import ipywidgets as widgets

price = widgets.FloatSlider(value=10, min=0, max=50, step=0.5, description="Price")
qty = widgets.IntSlider(value=3, min=1, max=20, description="Qty")
total = widgets.Label()
log = []

def update(change=None):
    total.value = f"Total: {price.value * qty.value:.2f}"

price.observe(update, names="value")
qty.observe(update, names="value")
qty.observe(lambda ch: log.append((ch["old"], ch["new"])), names="value")
update()
ui = widgets.VBox([price, qty, total])     # display(ui) in a notebook

qty.value = 5                              # simulate the user moving a slider
print(total.value)                         # Total: 50.00
print(log)                                 # [(3, 5)]

Remember

  • interact builds controls from function arguments in one line
  • Widgets have a value; react with observe(..., names='value') or on_click
  • Send callback output to a widgets.Output() area

Watch out for

  • Printing from a widget callback without an Output widget, so the output appears in the log instead of under the widget.

Check yourself

  1. With `@interact(n=(0, 10))`, what control does `n` get?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: ipywidgets.readthedocs.io/en/stable/

Builds on

Unlocks

Nothing builds on this yet.