0
# Qt Interface
1
2
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.
3
4
## Capabilities
5
6
### Qt Viewer Integration
7
8
Qt-based implementation of the napari viewer providing the main GUI application window and widget integration.
9
10
```python { .api }
11
class QtViewer:
12
"""
13
Qt-based viewer implementation providing GUI functionality.
14
Integrates the viewer model with Qt widgets and event handling.
15
"""
16
17
def __init__(self, viewer, parent=None):
18
"""
19
Create Qt viewer widget.
20
21
Parameters:
22
- viewer: ViewerModel instance
23
- parent: Parent Qt widget
24
"""
25
26
@property
27
def viewer(self):
28
"""Access to underlying ViewerModel."""
29
30
@property
31
def canvas(self):
32
"""Access to the vispy canvas for rendering."""
33
34
@property
35
def controls(self):
36
"""Access to layer control widgets."""
37
```
38
39
### Application Window
40
41
Main application window class providing the complete napari GUI with menus, toolbars, and widget management.
42
43
```python { .api }
44
class Window:
45
"""
46
Main napari application window.
47
Provides complete GUI with menus, docking widgets, and application controls.
48
"""
49
50
def __init__(self, viewer=None, *, show=True):
51
"""
52
Create main application window.
53
54
Parameters:
55
- viewer: ViewerModel instance (creates new if None)
56
- show: Whether to show window immediately
57
"""
58
59
@property
60
def qt_viewer(self) -> QtViewer:
61
"""Access to the Qt viewer widget."""
62
63
@property
64
def viewer(self):
65
"""Access to the viewer model."""
66
67
def add_dock_widget(self, widget, *, name=None, area='right'):
68
"""
69
Add a widget to the window as a docked panel.
70
71
Parameters:
72
- widget: Qt widget to dock
73
- name: Widget name for identification
74
- area: Dock area ('left', 'right', 'top', 'bottom')
75
"""
76
77
def remove_dock_widget(self, widget):
78
"""
79
Remove a docked widget from the window.
80
81
Parameters:
82
- widget: Widget to remove
83
"""
84
```
85
86
### Qt Widget Components
87
88
Individual Qt widgets used throughout the napari interface for specific functionality.
89
90
```python { .api }
91
class QtViewerButtons:
92
"""
93
Qt widget providing viewer control buttons.
94
Includes layer controls, view controls, and mode buttons.
95
"""
96
97
class QtToolTipLabel:
98
"""
99
Qt widget for displaying contextual tooltip information.
100
Provides rich text tooltips with formatting support.
101
"""
102
```
103
104
### Threading Support
105
106
Utilities for creating and managing worker threads for background processing without blocking the GUI.
107
108
```python { .api }
109
def create_worker(
110
func,
111
*args,
112
_start_thread=None,
113
_connect=None,
114
**kwargs
115
):
116
"""
117
Create a worker thread for running functions in the background.
118
119
Parameters:
120
- func: Function to run in worker thread
121
- args: Arguments for the function
122
- _start_thread: Whether to start thread immediately
123
- _connect: Dictionary of signal connections
124
- kwargs: Keyword arguments for the function
125
126
Returns:
127
Worker object with threading functionality
128
"""
129
130
def thread_worker(
131
func=None,
132
*,
133
start_thread=None,
134
connect=None
135
):
136
"""
137
Decorator for creating worker thread functions.
138
139
Parameters:
140
- func: Function to decorate
141
- start_thread: Whether to start thread on creation
142
- connect: Signal connection configuration
143
144
Returns:
145
Decorated function that creates worker threads when called
146
"""
147
```
148
149
### Qt Application Management
150
151
Functions for managing the Qt application instance and event loop lifecycle.
152
153
```python { .api }
154
def get_qapp():
155
"""
156
Get or create the Qt application instance.
157
158
Returns:
159
QApplication: The Qt application instance
160
"""
161
162
def run(
163
*,
164
force: bool = False,
165
gui_exceptions: bool = False,
166
max_loop_level: int = 1
167
):
168
"""
169
Start the Qt event loop for GUI applications.
170
171
Parameters:
172
- force: Force running even if event loop exists
173
- gui_exceptions: Show GUI dialogs for unhandled exceptions
174
- max_loop_level: Maximum nesting level for event loop
175
"""
176
```
177
178
### Styling and Resources
179
180
Functions for managing Qt stylesheets and visual resources.
181
182
```python { .api }
183
def get_stylesheet(theme: str = None):
184
"""
185
Get napari stylesheet for a specific theme.
186
187
Parameters:
188
- theme: Theme name ('dark', 'light', etc.)
189
190
Returns:
191
str: CSS stylesheet content
192
"""
193
194
def get_current_stylesheet():
195
"""
196
Get the currently active stylesheet.
197
198
Returns:
199
str: Current CSS stylesheet content
200
"""
201
```
202
203
## Usage Examples
204
205
### Basic Qt Application
206
207
```python
208
import napari
209
import numpy as np
210
211
# Create data
212
image_data = np.random.random((100, 100))
213
214
# Create napari application (automatically creates Qt app)
215
viewer = napari.Viewer()
216
viewer.add_image(image_data, name='Sample')
217
218
# Start Qt event loop
219
napari.run()
220
```
221
222
### Custom Window with Docked Widgets
223
224
```python
225
import napari
226
from qtpy.QtWidgets import QLabel, QVBoxLayout, QWidget
227
import numpy as np
228
229
# Create custom widget
230
class InfoWidget(QWidget):
231
def __init__(self):
232
super().__init__()
233
layout = QVBoxLayout()
234
layout.addWidget(QLabel("Custom Info Panel"))
235
layout.addWidget(QLabel("Layer count: 0"))
236
self.setLayout(layout)
237
238
# Create viewer and window
239
viewer = napari.Viewer()
240
window = napari.qt.Window(viewer)
241
242
# Add custom docked widget
243
info_widget = InfoWidget()
244
window.add_dock_widget(info_widget, name='Info', area='right')
245
246
# Add some data
247
image_data = np.random.random((100, 100))
248
viewer.add_image(image_data, name='Sample')
249
250
napari.run()
251
```
252
253
### Background Processing with Workers
254
255
```python
256
import napari
257
import numpy as np
258
import time
259
260
# Define long-running function
261
def process_data(data):
262
"""Simulate expensive computation."""
263
time.sleep(2) # Simulate processing time
264
return data * 2 + np.random.random(data.shape) * 0.1
265
266
# Create viewer
267
viewer = napari.Viewer()
268
original_data = np.random.random((100, 100))
269
viewer.add_image(original_data, name='Original')
270
271
# Create worker for background processing
272
worker = napari.qt.create_worker(process_data, original_data)
273
274
# Connect worker signals
275
def on_result(result):
276
viewer.add_image(result, name='Processed')
277
278
def on_error(error):
279
print(f"Processing failed: {error}")
280
281
worker.returned.connect(on_result)
282
worker.errored.connect(on_error)
283
284
# Start the worker
285
worker.start()
286
287
napari.run()
288
```
289
290
### Thread Worker Decorator
291
292
```python
293
import napari
294
import numpy as np
295
import time
296
297
@napari.qt.thread_worker
298
def background_analysis(image_data):
299
"""Perform analysis in background thread."""
300
# Simulate analysis
301
time.sleep(1)
302
303
# Calculate some statistics
304
mean_val = np.mean(image_data)
305
std_val = np.std(image_data)
306
307
# Generate result
308
result = {
309
'mean': mean_val,
310
'std': std_val,
311
'processed': image_data > mean_val
312
}
313
314
return result
315
316
# Create viewer
317
viewer = napari.Viewer()
318
data = np.random.random((100, 100))
319
viewer.add_image(data, name='Original')
320
321
# Start background analysis
322
worker = background_analysis(data)
323
324
# Handle results
325
def show_results(result):
326
print(f"Analysis complete - Mean: {result['mean']:.3f}, Std: {result['std']:.3f}")
327
viewer.add_labels(result['processed'].astype(int), name='Above Mean')
328
329
worker.returned.connect(show_results)
330
worker.start()
331
332
napari.run()
333
```
334
335
### Qt Application Integration
336
337
```python
338
import napari
339
from qtpy.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton
340
import numpy as np
341
342
# Create Qt application
343
app = napari.qt.get_qapp()
344
345
# Create custom main window
346
class CustomMainWindow(QMainWindow):
347
def __init__(self):
348
super().__init__()
349
self.setWindowTitle("Custom Napari App")
350
351
# Create central widget
352
central_widget = QWidget()
353
layout = QVBoxLayout()
354
355
# Add napari viewer
356
self.viewer = napari.Viewer()
357
layout.addWidget(self.viewer.window.qt_viewer)
358
359
# Add custom button
360
button = QPushButton("Add Random Image")
361
button.clicked.connect(self.add_random_image)
362
layout.addWidget(button)
363
364
central_widget.setLayout(layout)
365
self.setCentralWidget(central_widget)
366
367
def add_random_image(self):
368
data = np.random.random((100, 100))
369
self.viewer.add_image(data, name=f'Random {len(self.viewer.layers)}')
370
371
# Create and show window
372
window = CustomMainWindow()
373
window.show()
374
375
# Run application
376
app.exec_()
377
```
378
379
### Styling and Themes
380
381
```python
382
import napari
383
384
# Get current stylesheet
385
current_style = napari.qt.get_current_stylesheet()
386
print("Current theme active")
387
388
# Create viewer with specific styling
389
viewer = napari.Viewer()
390
391
# The viewer will use the current napari theme
392
# Themes can be changed through napari preferences or programmatically
393
# through the napari settings system
394
395
napari.run()
396
```