I've set a custom property on a widget using
setProperty("cssClass", "welcome")and I'm trying to select and style this widget from my stylesheet, but it's not working. What am I doing wrong?
Qt stylesheets support property selectors that let you target widgets based on custom properties — this is a great way to apply styles to specific groups of widgets without subclassing. However, there are a couple of common stumbling blocks that can prevent it from working. Let's walk through how to get this right.
The property selector syntax
In Qt stylesheets, you can select widgets by their properties using square bracket notation, similar to CSS attribute selectors. The general form looks like this:
QWidget[propertyName="value"] {
/* styles go here */
}
If you've set a property on a widget like this:
widget.setProperty("cssClass", "welcome")
Then the matching selector in your stylesheet would be:
QWidget[cssClass="welcome"] {
background-color: #3498db;
color: white;
}
A missing closing quote
Looking at the original attempt, there's a small but significant typo — the closing double quote around the property value is missing:
/* ❌ Missing closing quote */
QWidget[cssClass="welcome] {
}
It should be:
/* ✅ Correct */
QWidget[cssClass="welcome"] {
}
That missing " after welcome is enough to make the entire selector invalid, so no styles will be applied.
Applying stylesheets after setting properties
One thing to be aware of: Qt evaluates stylesheet selectors against widget properties at the time the stylesheet is applied. If you set a property after the stylesheet has already been applied, the widget may not pick up the new style automatically.
To handle this, you can either:
- Set the property before applying the stylesheet.
- Call
unpolishandpolishon the widget's style to force a re-evaluation after changing a property.
Here's how you'd force a style refresh:
widget.setProperty("cssClass", "welcome")
widget.style().unpolish(widget)
widget.style().polish(widget)
This tells Qt to re-evaluate the stylesheet rules for that widget with its current properties.
A complete working example
Here's a full example that creates two labels — one with a custom cssClass property and one without — so you can see the property selector in action. If you're new to building interfaces with PyQt6, you may want to start with the creating your first window tutorial first.
import sys
from PyQt6.QtWidgets import (
QApplication, QWidget, QLabel, QVBoxLayout
)
app = QApplication(sys.argv)
# Define the stylesheet with a property selector.
app.setStyleSheet("""
QLabel[cssClass="welcome"] {
background-color: #2ecc71;
color: white;
font-size: 18px;
padding: 10px;
border-radius: 5px;
}
QLabel[cssClass="warning"] {
background-color: #e74c3c;
color: white;
font-size: 18px;
padding: 10px;
border-radius: 5px;
}
QLabel {
font-size: 14px;
padding: 5px;
}
""")
window = QWidget()
window.setWindowTitle("Property Selector Demo")
layout = QVBoxLayout()
# This label will match the [cssClass="welcome"] selector.
welcome_label = QLabel("Welcome! This label has cssClass='welcome'")
welcome_label.setProperty("cssClass", "welcome")
# This label will match the [cssClass="warning"] selector.
warning_label = QLabel("Watch out! This label has cssClass='warning'")
warning_label.setProperty("cssClass", "warning")
# This label has no custom property, so only the generic QLabel style applies.
plain_label = QLabel("This is a plain label with no custom property.")
layout.addWidget(welcome_label)
layout.addWidget(warning_label)
layout.addWidget(plain_label)
window.setLayout(layout)
window.show()
sys.exit(app.exec())
When you run this, you'll see three labels: a green one styled by the welcome selector, a red one styled by the warning selector, and a plain one that only picks up the default QLabel style. The example uses a QVBoxLayout to arrange the labels vertically.
Loading styles from an external file
If you prefer to keep your styles in a separate .css file (which is a good idea for larger applications), you can load the file and apply it like this:
with open("style.css", "r") as f:
app.setStyleSheet(f.read())
Your style.css file would then contain the same stylesheet rules:
QLabel[cssClass="welcome"] {
background-color: #2ecc71;
color: white;
font-size: 18px;
padding: 10px;
border-radius: 5px;
}
Just make sure the file path is correct relative to where you're running your script, or use an absolute path. For larger projects, you might also want to consider using the Qt Resource system to bundle your stylesheet files with your application.
Summary
Custom property selectors are a flexible way to style specific widgets in Qt without creating subclasses or applying inline styles everywhere. If you need even more control over widget appearance, you can also create your own custom widgets. Keep these points in mind:
- The syntax is
QWidget[property="value"]— make sure both quotes are present. - Set properties before the stylesheet is applied, or use
unpolish/polishto refresh the style after changing a property. - You can use any property name you like —
cssClassis a perfectly fine convention, but you could equally userole,category, or anything else that makes sense for your application.
Packaging Python Applications with PyInstaller by Martin Fitzpatrick — This step-by-step guide walks you through packaging your own Python applications from simple examples to complete installers and signed executables.