n-dimensional array viewer in Python with fast, interactive multi-dimensional image visualization
—
The Qt interface provides the graphical user interface components, window management, threading utilities, and event loop controls for napari's desktop application functionality. Built on the Qt framework with support for multiple Qt backends.
Qt-based implementation of the napari viewer providing the main GUI application window and widget integration.
class QtViewer:
"""
Qt-based viewer implementation providing GUI functionality.
Integrates the viewer model with Qt widgets and event handling.
"""
def __init__(self, viewer, parent=None):
"""
Create Qt viewer widget.
Parameters:
- viewer: ViewerModel instance
- parent: Parent Qt widget
"""
@property
def viewer(self):
"""Access to underlying ViewerModel."""
@property
def canvas(self):
"""Access to the vispy canvas for rendering."""
@property
def controls(self):
"""Access to layer control widgets."""Main application window class providing the complete napari GUI with menus, toolbars, and widget management.
class Window:
"""
Main napari application window.
Provides complete GUI with menus, docking widgets, and application controls.
"""
def __init__(self, viewer=None, *, show=True):
"""
Create main application window.
Parameters:
- viewer: ViewerModel instance (creates new if None)
- show: Whether to show window immediately
"""
@property
def qt_viewer(self) -> QtViewer:
"""Access to the Qt viewer widget."""
@property
def viewer(self):
"""Access to the viewer model."""
def add_dock_widget(self, widget, *, name=None, area='right'):
"""
Add a widget to the window as a docked panel.
Parameters:
- widget: Qt widget to dock
- name: Widget name for identification
- area: Dock area ('left', 'right', 'top', 'bottom')
"""
def remove_dock_widget(self, widget):
"""
Remove a docked widget from the window.
Parameters:
- widget: Widget to remove
"""Individual Qt widgets used throughout the napari interface for specific functionality.
class QtViewerButtons:
"""
Qt widget providing viewer control buttons.
Includes layer controls, view controls, and mode buttons.
"""
class QtToolTipLabel:
"""
Qt widget for displaying contextual tooltip information.
Provides rich text tooltips with formatting support.
"""Utilities for creating and managing worker threads for background processing without blocking the GUI.
def create_worker(
func,
*args,
_start_thread=None,
_connect=None,
**kwargs
):
"""
Create a worker thread for running functions in the background.
Parameters:
- func: Function to run in worker thread
- args: Arguments for the function
- _start_thread: Whether to start thread immediately
- _connect: Dictionary of signal connections
- kwargs: Keyword arguments for the function
Returns:
Worker object with threading functionality
"""
def thread_worker(
func=None,
*,
start_thread=None,
connect=None
):
"""
Decorator for creating worker thread functions.
Parameters:
- func: Function to decorate
- start_thread: Whether to start thread on creation
- connect: Signal connection configuration
Returns:
Decorated function that creates worker threads when called
"""Functions for managing the Qt application instance and event loop lifecycle.
def get_qapp():
"""
Get or create the Qt application instance.
Returns:
QApplication: The Qt application instance
"""
def run(
*,
force: bool = False,
gui_exceptions: bool = False,
max_loop_level: int = 1
):
"""
Start the Qt event loop for GUI applications.
Parameters:
- force: Force running even if event loop exists
- gui_exceptions: Show GUI dialogs for unhandled exceptions
- max_loop_level: Maximum nesting level for event loop
"""Functions for managing Qt stylesheets and visual resources.
def get_stylesheet(theme: str = None):
"""
Get napari stylesheet for a specific theme.
Parameters:
- theme: Theme name ('dark', 'light', etc.)
Returns:
str: CSS stylesheet content
"""
def get_current_stylesheet():
"""
Get the currently active stylesheet.
Returns:
str: Current CSS stylesheet content
"""import napari
import numpy as np
# Create data
image_data = np.random.random((100, 100))
# Create napari application (automatically creates Qt app)
viewer = napari.Viewer()
viewer.add_image(image_data, name='Sample')
# Start Qt event loop
napari.run()import napari
from qtpy.QtWidgets import QLabel, QVBoxLayout, QWidget
import numpy as np
# Create custom widget
class InfoWidget(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
layout.addWidget(QLabel("Custom Info Panel"))
layout.addWidget(QLabel("Layer count: 0"))
self.setLayout(layout)
# Create viewer and window
viewer = napari.Viewer()
window = napari.qt.Window(viewer)
# Add custom docked widget
info_widget = InfoWidget()
window.add_dock_widget(info_widget, name='Info', area='right')
# Add some data
image_data = np.random.random((100, 100))
viewer.add_image(image_data, name='Sample')
napari.run()import napari
import numpy as np
import time
# Define long-running function
def process_data(data):
"""Simulate expensive computation."""
time.sleep(2) # Simulate processing time
return data * 2 + np.random.random(data.shape) * 0.1
# Create viewer
viewer = napari.Viewer()
original_data = np.random.random((100, 100))
viewer.add_image(original_data, name='Original')
# Create worker for background processing
worker = napari.qt.create_worker(process_data, original_data)
# Connect worker signals
def on_result(result):
viewer.add_image(result, name='Processed')
def on_error(error):
print(f"Processing failed: {error}")
worker.returned.connect(on_result)
worker.errored.connect(on_error)
# Start the worker
worker.start()
napari.run()import napari
import numpy as np
import time
@napari.qt.thread_worker
def background_analysis(image_data):
"""Perform analysis in background thread."""
# Simulate analysis
time.sleep(1)
# Calculate some statistics
mean_val = np.mean(image_data)
std_val = np.std(image_data)
# Generate result
result = {
'mean': mean_val,
'std': std_val,
'processed': image_data > mean_val
}
return result
# Create viewer
viewer = napari.Viewer()
data = np.random.random((100, 100))
viewer.add_image(data, name='Original')
# Start background analysis
worker = background_analysis(data)
# Handle results
def show_results(result):
print(f"Analysis complete - Mean: {result['mean']:.3f}, Std: {result['std']:.3f}")
viewer.add_labels(result['processed'].astype(int), name='Above Mean')
worker.returned.connect(show_results)
worker.start()
napari.run()import napari
from qtpy.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton
import numpy as np
# Create Qt application
app = napari.qt.get_qapp()
# Create custom main window
class CustomMainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Custom Napari App")
# Create central widget
central_widget = QWidget()
layout = QVBoxLayout()
# Add napari viewer
self.viewer = napari.Viewer()
layout.addWidget(self.viewer.window.qt_viewer)
# Add custom button
button = QPushButton("Add Random Image")
button.clicked.connect(self.add_random_image)
layout.addWidget(button)
central_widget.setLayout(layout)
self.setCentralWidget(central_widget)
def add_random_image(self):
data = np.random.random((100, 100))
self.viewer.add_image(data, name=f'Random {len(self.viewer.layers)}')
# Create and show window
window = CustomMainWindow()
window.show()
# Run application
app.exec_()import napari
# Get current stylesheet
current_style = napari.qt.get_current_stylesheet()
print("Current theme active")
# Create viewer with specific styling
viewer = napari.Viewer()
# The viewer will use the current napari theme
# Themes can be changed through napari preferences or programmatically
# through the napari settings system
napari.run()Install with Tessl CLI
npx tessl i tessl/pypi-napari