Widgets and interactive output

Build sliders, dropdowns and live plots with ipywidgets, keep the update logic out of the widget handler, and know what stops working when you export.

Start with interact

# pip install ipywidgets
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, IntSlider, Dropdown

@interact(n=IntSlider(min=10, max=500, value=100, step=10),
          kind=Dropdown(options=["sine", "cosine"]))
def draw(n=100, kind="sine"):
    x = np.linspace(0, 4 * np.pi, n)
    y = np.sin(x) if kind == "sine" else np.cos(x)
    plt.figure(figsize=(5, 2.5))
    plt.plot(x, y)
    plt.show()

interact infers a widget from each parameter's type and default. A slider for an int, a checkbox for a bool, a text box for a str. That is enough for most exploration.

WidgetUse for
IntSlider / FloatSliderNumeric ranges where the exact value matters
Dropdown / SelectChoosing one item from a known set
Text / TextareaFree-form input, queries, prompts
Checkbox / ToggleButtonBooleans and feature flags
OutputCapturing output in one place instead of appending forever

Wiring widgets explicitly

import ipywidgets as w

slider = w.IntSlider(value=3, min=1, max=10, description="degree")
out = w.Output()

def refresh(change):
    with out:
        out.clear_output(wait=True)          # avoid output piling up
        poly = np.polyfit(x, y, change["new"])
        print("residual:", float(np.sum((y - np.polyval(poly, x)) ** 2)))

slider.observe(refresh, names="value")
display(w.VBox([slider, out]))
  • Handlers receive a change dict; read change["new"] rather than closing over a stale variable.
  • out.clear_output(wait=True) replaces output instead of appending, which keeps long sessions responsive.
  • For anything substantial, dispatch to a function defined in a module so the logic is testable without a browser.

Widgets and the export problem

Widget state lives in the live kernel and is synchronised over the cell protocol. A saved .ipynb stores the widget model, not the behaviour: opening it without a running kernel shows a dead control.

💡
If the interactive version matters, serve it with Voila, which runs the notebook as a standalone web app with a live kernel. If a static report matters, export figures and tables instead and keep the widgets as a local exploration tool.

FAQ

My widget shows "Loading widget..." forever. What is wrong?
The front end and the kernel disagree about the ipywidgets version, or the notebook was saved with widget state but opened without a kernel. Reinstall ipywidgets and jupyterlab-widgets in the same environment and restart the kernel.
Can I run the same widget from a script?
The widget machinery needs a running notebook or Voila server. Move the calculation into a plain function, call that from the widget handler, and test the function directly.

Visualisation inside notebooks Beyond local notebooks: Colab, Voila and Quarto

Last refreshed 2026-09-18.