Skip to content

Your First GUI

You can either use one of the existing applications (pymmcore-gui or napari-micromanager), or build your own from pymmcore-widgets, a library of Qt widgets for controlling a CMMCorePlus.

Using an application

Once it's installed (from GitHub, or as a bundled app for Windows and macOS), start it with the demo devices:

mmgui run --demo-config

Without --demo-config, the app starts with no devices loaded. You can load a configuration from the Devices menu, or start with mmgui -c path/to/config.cfg. See Using pymmcore-gui for more.

Once it's installed, start it with:

napari-micromanager

Then pick a configuration file at the top left of the window (or start it with napari-micromanager -c path/to/config.cfg).

Building your own

Widgets in pymmcore-widgets use the global CMMCorePlus.instance() by default (see the tip in First steps), and they listen to the core's events, so if you change something from a script (or from another widget), they'll update to match. (A few widgets don't use a core at all. The sequence editors, like ChannelTable and MDASequenceWidget, just edit useq objects.)

You'll need pymmcore-widgets and a Qt backend, PyQt6 or PySide6 (see Installation, and PyQt6 or PySide6? if you're not sure which). The examples here import Qt from qtpy, so they run with either one.

Then combine widgets like any other Qt widgets:

from pymmcore_plus import CMMCorePlus
from qtpy.QtWidgets import QApplication, QHBoxLayout, QVBoxLayout, QWidget

from pymmcore_widgets import (
    ChannelWidget,
    ExposureWidget,
    ImagePreview,
    LiveButton,
    SnapButton,
)

app = QApplication([])

core = CMMCorePlus.instance()  # (1)!
core.loadSystemConfiguration()

window = QWidget()
controls = QHBoxLayout()
controls.addWidget(ChannelWidget())
controls.addWidget(ExposureWidget())
controls.addWidget(SnapButton())
controls.addWidget(LiveButton())

layout = QVBoxLayout(window)
layout.addLayout(controls)
layout.addWidget(ImagePreview())
window.show()

app.exec()
  1. This is the core the widgets below will use, so loading the configuration here is enough for all of them. Pass mmcore=... to a widget to use a different core (the ConfigWizard calls it core=).

A slightly larger version of this example (custom_gui.py, which adds a configuration loader and a few more controls) looks like this:

Next steps

The widget gallery is the best place to find widgets for your own GUI (each one has a screenshot and a runnable example). Building a custom GUI walks through the larger example above, and Qt integration explains how to keep the GUI responsive while the hardware is busy.