0
# PyQtDarkTheme
1
2
A comprehensive theming library for Qt-based Python applications (PySide and PyQt) that applies flat dark and light themes with automatic OS synchronization capabilities. Provides seamless theme switching, automatic detection and synchronization with operating system appearance settings, customizable styling options, and built-in support for HiDPI displays.
3
4
## Package Information
5
6
- **Package Name**: qdarktheme (installed as pyqtdarktheme)
7
- **Language**: Python
8
- **Installation**: `pip install pyqtdarktheme`
9
- **Requirements**: Python 3.7+, Qt 5.15+, PySide6/PyQt6/PyQt5/PySide2
10
11
## Core Imports
12
13
```python
14
import qdarktheme
15
```
16
17
## Basic Usage
18
19
```python
20
import sys
21
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton
22
import qdarktheme
23
24
# Enable HiDPI support (call before QApplication)
25
qdarktheme.enable_hi_dpi()
26
27
app = QApplication(sys.argv)
28
29
# Apply complete dark theme to your Qt application
30
qdarktheme.setup_theme()
31
32
main_win = QMainWindow()
33
push_button = QPushButton("Dark Theme Example")
34
main_win.setCentralWidget(push_button)
35
main_win.show()
36
37
app.exec()
38
```
39
40
## Architecture
41
42
PyQtDarkTheme uses a modular architecture:
43
44
- **Theme System**: Dark, light, and auto themes with OS synchronization
45
- **Style Loader**: Template-based stylesheet generation with color customization
46
- **Palette System**: QPalette objects for themes with proper color roles
47
- **OS Integration**: Automatic theme detection and accent color synchronization
48
- **Qt Compatibility**: Abstraction layer supporting multiple Qt bindings
49
- **Proxy Style**: Enhanced styling through QProxyStyle implementation
50
51
## Capabilities
52
53
### Complete Theme Application
54
55
Apply comprehensive theming to Qt applications with customization options and OS synchronization.
56
57
```python { .api }
58
def setup_theme(
59
theme: str = "dark",
60
corner_shape: str = "rounded",
61
custom_colors: dict[str, str | dict[str, str]] | None = None,
62
additional_qss: str | None = None,
63
*,
64
default_theme: str = "dark",
65
) -> None:
66
"""
67
Apply the theme which looks like flat design to the Qt App completely.
68
69
Args:
70
theme: Theme name - "dark", "light", or "auto"
71
If "auto", sync with OS theme and accent (Mac accent support)
72
Falls back to default_theme if OS detection fails
73
corner_shape: Corner style - "rounded" or "sharp"
74
custom_colors: Color customization map
75
Format: {"color_id": "#hex"} or {"[theme]": {"color_id": "#hex"}}
76
Example: {"primary": "#D0BCFF"} or {"[dark]": {"primary": "#D0BCFF"}}
77
additional_qss: Additional stylesheet text to append
78
default_theme: Fallback theme when auto detection fails
79
80
Raises:
81
ValueError: Invalid theme/corner_shape values
82
KeyError: Invalid color IDs in custom_colors
83
Exception: QApplication not instantiated
84
85
Examples:
86
# Dark theme
87
qdarktheme.setup_theme("dark")
88
89
# Auto sync with OS
90
qdarktheme.setup_theme("auto")
91
92
# Custom colors
93
qdarktheme.setup_theme(custom_colors={"primary": "#D0BCFF"})
94
95
# Theme-specific colors
96
qdarktheme.setup_theme(
97
theme="auto",
98
custom_colors={"[dark]": {"primary": "#D0BCFF"}}
99
)
100
"""
101
```
102
103
### Stylesheet Loading
104
105
Load theme stylesheets as strings for manual application.
106
107
```python { .api }
108
def load_stylesheet(
109
theme: str = "dark",
110
corner_shape: str = "rounded",
111
custom_colors: dict[str, str | dict[str, str]] | None = None,
112
*,
113
default_theme: str = "dark",
114
) -> str:
115
"""
116
Load the style sheet which looks like flat design.
117
118
Args:
119
theme: Theme name - "dark", "light", or "auto"
120
corner_shape: Corner style - "rounded" or "sharp"
121
custom_colors: Color customization map
122
default_theme: Fallback theme for auto detection failures
123
124
Returns:
125
Stylesheet string for Qt application
126
127
Raises:
128
ValueError: Invalid theme/corner_shape arguments
129
KeyError: Invalid color IDs in custom_colors
130
131
Examples:
132
# Basic usage
133
app.setStyleSheet(qdarktheme.load_stylesheet())
134
135
# Light theme
136
app.setStyleSheet(qdarktheme.load_stylesheet("light"))
137
138
# Auto with OS sync
139
app.setStyleSheet(qdarktheme.load_stylesheet("auto"))
140
141
# Custom colors
142
app.setStyleSheet(qdarktheme.load_stylesheet(
143
custom_colors={"primary": "#D0BCFF"}
144
))
145
"""
146
```
147
148
### Palette Loading
149
150
Load theme QPalette objects for color role customization.
151
152
```python { .api }
153
def load_palette(
154
theme: str = "dark",
155
custom_colors: dict[str, str | dict[str, str]] | None = None,
156
*,
157
default_theme: str = "dark",
158
for_stylesheet: bool = False,
159
):
160
"""
161
Load the QPalette for the dark or light theme.
162
163
Args:
164
theme: Theme name - "dark", "light", or "auto"
165
custom_colors: Color customization map
166
default_theme: Fallback theme for auto detection failures
167
for_stylesheet: If True, only colors not settable via stylesheets
168
169
Returns:
170
QPalette object configured for the theme
171
172
Raises:
173
TypeError: Invalid theme argument type
174
KeyError: Invalid color IDs in custom_colors
175
176
Examples:
177
# Basic usage
178
app.setPalette(qdarktheme.load_palette())
179
180
# Light theme
181
app.setPalette(qdarktheme.load_palette("light"))
182
183
# Auto detection
184
app.setPalette(qdarktheme.load_palette("auto"))
185
186
# Custom colors
187
app.setPalette(qdarktheme.load_palette(
188
custom_colors={"primary": "#D0BCFF"}
189
))
190
"""
191
```
192
193
### HiDPI Support
194
195
Enable high-resolution display support for Qt applications.
196
197
```python { .api }
198
def enable_hi_dpi() -> None:
199
"""
200
Allow to HiDPI.
201
202
This function must be set before instantiation of QApplication.
203
For Qt6 bindings, HiDPI "just works" without using this function.
204
205
Examples:
206
# Enable before QApplication
207
qdarktheme.enable_hi_dpi()
208
app = QApplication(sys.argv)
209
qdarktheme.setup_theme()
210
"""
211
```
212
213
### Theme Synchronization Control
214
215
Control automatic OS theme synchronization.
216
217
```python { .api }
218
def stop_sync() -> None:
219
"""
220
Stop sync with system theme.
221
222
Stops the background listener that monitors OS theme changes
223
when using theme="auto" mode.
224
225
Examples:
226
# Stop OS synchronization
227
qdarktheme.stop_sync()
228
"""
229
```
230
231
### Cache Management
232
233
Manage theme resource caches stored in system home directory.
234
235
```python { .api }
236
def clear_cache() -> None:
237
"""
238
Clear the caches in system home path.
239
240
PyQtDarkTheme builds caches of resources in the system home path.
241
You can clear the caches by running this method.
242
243
Cache location: ~/.cache/qdarktheme/v{version}/
244
245
Examples:
246
# Clear all cached resources
247
qdarktheme.clear_cache()
248
"""
249
```
250
251
### Theme Enumeration
252
253
Query available theme names for validation and UI purposes.
254
255
```python { .api }
256
def get_themes() -> tuple[str, ...]:
257
"""
258
Return available theme names.
259
260
Returns:
261
Tuple of available theme names: ("dark", "light", "auto")
262
263
Examples:
264
# Get all available themes
265
themes = qdarktheme.get_themes()
266
print(themes) # ("dark", "light", "auto")
267
"""
268
```
269
270
## Types and Constants
271
272
```python { .api }
273
# Package version
274
__version__: str = "2.1.0"
275
276
# Color customization type
277
ColorMap = dict[str, str | dict[str, str]]
278
279
# Theme names
280
THEMES = ("dark", "light", "auto")
281
282
# Corner shapes
283
CORNER_SHAPES = ("rounded", "sharp")
284
```
285
286
## Command Line Tools
287
288
### Widget Gallery
289
290
Interactive demonstration of all Qt widgets with theme applied.
291
292
```bash
293
# Run widget gallery demo
294
python -m qdarktheme.widget_gallery
295
```
296
297
This launches a comprehensive showcase of Qt widgets styled with the current theme, useful for testing theme appearance and compatibility.
298
299
## Advanced Usage
300
301
### Theme-Specific Color Customization
302
303
Customize colors for specific themes only:
304
305
```python
306
# Different colors for dark and light themes
307
qdarktheme.setup_theme(
308
theme="auto",
309
custom_colors={
310
"[dark]": {
311
"primary": "#D0BCFF",
312
"primary>selection.background": "#6750A4"
313
},
314
"[light]": {
315
"primary": "#6750A4",
316
"primary>selection.background": "#D0BCFF"
317
}
318
}
319
)
320
```
321
322
### Manual Stylesheet and Palette Application
323
324
For advanced control, load components separately:
325
326
```python
327
# Load components individually
328
palette = qdarktheme.load_palette(theme="dark")
329
stylesheet = qdarktheme.load_stylesheet(theme="dark")
330
331
app.setPalette(palette)
332
app.setStyleSheet(stylesheet)
333
```
334
335
### Error Handling
336
337
Common exceptions and handling patterns:
338
339
```python
340
try:
341
qdarktheme.setup_theme("auto", custom_colors={"invalid_color": "#FF0000"})
342
except KeyError as e:
343
print(f"Invalid color ID: {e}")
344
except ValueError as e:
345
print(f"Invalid theme argument: {e}")
346
except Exception as e:
347
print(f"QApplication not instantiated: {e}")
348
```
349
350
## Platform Compatibility
351
352
- **Windows**: Full theme and accent synchronization
353
- **macOS**: Theme and accent color synchronization
354
- **Linux**: Theme synchronization (no accent colors)
355
- **Qt Versions**: Qt 5.15+ (PySide2, PySide6, PyQt5, PyQt6)
356
- **Python**: 3.7+ required