@stylesheet¶
The @stylesheet decorator applies a QSS or SCSS stylesheet to a widget class. Unlike @entrypoint's stylesheet option (which applies to the entire application), @stylesheet scopes styles to the decorated widget and its children.
Basic Usage¶
from qtpie import stylesheet, widget
from qtpy.QtWidgets import QWidget
@stylesheet("card.qss")
@widget
class Card(QWidget):
pass
The stylesheet is loaded when the widget is instantiated and applied via widget.setStyleSheet().
Parameters¶
path (positional, required)¶
Type: str
Path to a stylesheet. Supports three formats:
- Filesystem path - Regular file path (e.g.,
"styles.qss","styles/main.scss") - QRC path - Qt resource path starting with
:/(e.g.,":/styles/app.qss") - SCSS file - Any
.scssfile is automatically compiled to QSS
@stylesheet("styles.qss") # Plain QSS from filesystem
class MyWidget(QWidget):
pass
@stylesheet("styles.scss") # SCSS (compiled automatically)
class MyWidget(QWidget):
pass
@stylesheet(":/styles/app.qss") # QRC resource
class MyWidget(QWidget):
pass
watch¶
Type: bool
Default: False
Enable hot-reload. When True, changes to the stylesheet file are automatically detected and applied without restarting the app.
Note: Not applicable to QRC paths (resources are compiled into the binary).
@stylesheet("styles.scss", watch=True)
@widget
class MyWidget(QWidget):
pass
# Edit styles.scss and save - widget updates instantly!
scss_search_paths¶
Type: list[str] | None
Default: None
Directories to search when resolving SCSS @import statements. If None, the stylesheet's parent directory is used automatically.
@stylesheet(
"main.scss",
watch=True,
scss_search_paths=["partials/", "themes/"]
)
@widget
class MyWidget(QWidget):
pass
Examples¶
Simple QSS¶
from qtpie import stylesheet, widget, make
from qtpy.QtWidgets import QWidget, QLabel
@stylesheet("card.qss")
@widget
class Card(QWidget):
title: QLabel = make(QLabel, "Card Title")
card.qss:
QWidget {
background-color: white;
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
}
QLabel {
font-size: 18px;
font-weight: bold;
}
SCSS with Hot Reload¶
from qtpie import stylesheet, widget, make
from qtpy.QtWidgets import QWidget, QPushButton
@stylesheet("button.scss", watch=True)
@widget
class StyledButton(QWidget):
button: QPushButton = make(QPushButton, "Click Me")
button.scss:
$primary: #007bff;
$radius: 4px;
QPushButton {
background-color: $primary;
color: white;
border-radius: $radius;
padding: 8px 16px;
&:hover {
background-color: darken($primary, 10%);
}
}
SCSS with Imports¶
Project structure:
myapp/
├── styles/
│ ├── card.scss
│ └── partials/
│ ├── _variables.scss
│ └── _mixins.scss
└── widgets/
└── card.py
card.py:
from qtpie import stylesheet, widget, make
from qtpy.QtWidgets import QWidget, QLabel
@stylesheet(
"styles/card.scss",
watch=True,
scss_search_paths=["styles/partials"]
)
@widget
class Card(QWidget):
title: QLabel = make(QLabel, "Card")
styles/partials/_variables.scss:
styles/card.scss:
@import 'variables';
QWidget {
background-color: $bg-color;
border: 1px solid $border-color;
}
QLabel {
color: $text-color;
}
QRC Resources¶
For production apps, embed stylesheets in Qt resources:
from qtpie import stylesheet, widget
from qtpy.QtWidgets import QWidget
# resources.qrc compiled with rcc
import resources_rc # noqa: F401
@stylesheet(":/styles/card.qss")
@widget
class Card(QWidget):
pass
QRC paths start with :/ and reference compiled Qt resources. This is ideal for distribution since styles are embedded in the binary.
On App Subclass¶
You can also use @stylesheet on App subclasses to apply app-wide styles:
from qtpie import App, stylesheet
@stylesheet("app.scss", watch=True)
class MyApp(App):
def create_window(self):
return MainWindow()
Note: When used on App, the stylesheet is applied to the entire application, similar to @entrypoint(stylesheet=...).
Combining with @widget¶
The @stylesheet decorator works seamlessly with @widget. Place @stylesheet on the outside:
@stylesheet("styles.scss", watch=True)
@widget(layout="vertical", classes=["card"])
class MyWidget(QWidget):
label: QLabel = make(QLabel, "Hello")
button: QPushButton = make(QPushButton, "Click")
Comparison with Other Approaches¶
| Approach | Scope | Best For |
|---|---|---|
@stylesheet on widget |
Widget + children | Component-level styles, reusable styled components |
@entrypoint(stylesheet=...) |
Entire app | App-wide styles, simple apps |
@stylesheet on App |
Entire app | App-wide styles with App subclass |
watch_scss() / watch_qss() |
Manual target | Maximum control, dynamic paths |
When to Use @stylesheet¶
- Component libraries: Style reusable widgets independently
- Scoped styles: Keep styles isolated to specific widgets
- Multiple stylesheets: Different widgets with different styles
When to Use @entrypoint(stylesheet=...)¶
- Single-file apps: Simple setup, one stylesheet for everything
- App-wide themes: Consistent styling across all widgets
Watcher Lifecycle¶
When watch=True, a file watcher is created and stored on the widget instance. The watcher:
- Automatically stops when the widget is garbage collected
- Can be manually stopped via
widget._stylesheet_watcher.stop() - Handles editor save behaviors (delete + recreate, rapid saves)
Graceful Error Handling¶
If the stylesheet file doesn't exist:
- No error is raised
- The widget's stylesheet is set to empty string
- If
watch=True, the watcher monitors for the file to be created
This allows you to start your app before creating the stylesheet file.
See Also¶
- SCSS Hot Reload Guide - Detailed SCSS workflow
- @entrypoint - App-level stylesheet option
- Styling Basics - CSS classes and QSS fundamentals
- Class Helpers - Dynamic class manipulation