Skip to content

magicgui 🧙#

magicgui is a python library for building graphical user interfaces (GUIs).

It aims to speed up data workflows by providing a simple, consistent API for creating GUIs to control various data types, that work across various environments.

GUIs may be built manually using a variety of widgets, or generated automatically from python type hints.

magicgui organization#

magicgui can be thought of as performing two distinct tasks:

  1. Providing an simplified abstraction layer for GUI frameworks, allowing you to use the same API to create UIs that can move between environments and frameworks (such as a desktop app, or a Jupyter notebook).
  2. Providing a mapping of python types to widgets, allowing you to autogenerate graphical user interfaces for functions and dataclasses by annotating with standard python type hints.

While there is some degree of customizeability, the emphasis is on rapid development of relatively simple GUIs, with minimal boilerplate. For highly customized GUIs with complex layouts, it may be more appropriate to use a lower-level GUI framework.

The API is organized into 2 main levels:

Image title

magicgui API layers

Python Type Mapping#

At its highest level, magicgui provides a mapping of Python types to widgets. This API allows you to create graphical user interfaces for your functions and dataclasses simply by annotating them with standard python type hints.

Type hints??

Type hints are a way to annotate your code with information about the types of variables and function arguments. They are completely optional, but static type checkers and other libraries (like magicgui!) can use them to check your code and/or provide additional functionality.

Typically, they are provided after a colon following a variable name or function argument.

In the example below, param_a has been annotated as an int, param_b as a str, and the return value as a list.

def my_function(param_a: int, param_b: str) -> list:
    ...

If you are new to type annotations in Python, here are a few resources to get you started:

create_widget#

magicgui.widgets.create_widget is a general function, used throughout the library, that allows you to create a widget for a specific Python type or value:

from magicgui.widgets import create_widget

# passing a type to create_widget
widget = create_widget(annotation=int)
widget.show()

# passing a value to create_widget
widget2 = create_widget(value="Hello World")
widget2.show()

For more details on how magicgui maps types to widgets, see Type Mapping.

magicgui#

The magicgui.magicgui function is one way to autogenerate a compound Widget based on the parameters of a function:

from typing import Annotated, Literal

from magicgui import magicgui


@magicgui
def my_function(
    param_a: int,
    param_b: Annotated[int, {'widget_type': "Slider", 'max': 100}] = 42,
    param_c: Literal["First", "Second", "Third"] = "Second"
):
    print("param_a:", param_a)
    print("param_b:", param_b)
    print("param_c:", param_c)

# my_function now IS a widget, in addition to being a callable function
my_function.show()

For more details on using magicgui and magic_factory, see the magicgui decorators page.

guiclass#

magicgui.experimental.guiclass is a newer experimental feature that provides an object-oriented alternative to magicgui. It wraps dataclasses.dataclass and adds a gui attribute to the resulting class, which is a magicgui-generated widget that can be used to control the dataclass instance. (The widget is only created when the gui attribute is accessed for the first time.)

from magicgui.experimental import guiclass, button

@guiclass
class MyDataclass:
    a: int = 0
    b: str = 'hello'
    c: bool = True

    @button
    def compute(self):
        print(self.a, self.b, self.c)

obj = MyDataclass(a=10, b='foo')
obj.gui.show()

For more details on using the guiclass decorator, see Dataclasses & guiclass.

Widgets#

At the lower level, magicgui is a library of widgets (the individual elements that make up a graphical user interface). Each widget is customized to display and interact with a specific type of data. In some cases, it makes more sense to create and arrange these widgets manually, rather than using the type-based autogeneration features described above.

Magicgui acts as an abstraction layer for a variety of different GUI toolkits, allowing you to use the same API to create UIs that can move between environments (such as a desktop app, or a Jupyter notebook).

Currently, magicgui supports the following backends:

You can use magicgui.widgets to quickly build graphical user interfaces.

from magicgui import widgets

a = widgets.SpinBox(value=10, label="a")
b = widgets.Slider(value=20, min=0, max=100, label="b")
result = widgets.LineEdit(value=a.value * b.value, label="result")
button = widgets.PushButton(text="multiply")

@button.clicked.connect
def on_button_click():
    result.value = a.value * b.value

container = widgets.Container(widgets=[a, b, result, button])
container.show()

To learn more about the available widgets and how to use them, see the Widgets Overview.

...details

Behind the scenes, magicgui declares a set of WidgetProtocols that each backend must implement, and every magicgui Widget is a wrapper around a backend-specific widget. Most users will never need to worry about this, but it's good to know that it's there if you ever need to dig deeper.

Events#

All widgets (whether created directly or autogenerated based on type hints) emit events when their value changes or in response to interaction.

To learn about connecting custom functionality to these events, see Events.

Installation#

See installing magicgui.