pyqt-styling ยท diff
v1.0.0 to v2.1.0
4 added, 246 removed. Audit A to A.
---
name: pyqt-styling
- description: "PyQt/PySide6 QSS styling - selectors, properties, pseudo-states, dark theme, widget-specific styles"
+ description: "Use when styling PyQt/PySide6 widgets with QSS - selectors and pseudo-states, stylesheet application, common style properties, widget-specific styling, or building a dark theme"
metadata:
author: mte90
- version: 1.0.0
+ version: 2.1.0
tags:
- python
- qt
- pyqt
- pyside
- styling
- qss
- css
- themes
---
# PyQt Styling - QSS (Qt Style Sheets)
Complete guide to styling Qt applications with QSS.
## Basic Syntax
### Type Selectors
```css
/* Match all widgets of a type */
QLabel {
color: #333333;
font-size: 14px;
}
QPushButton {
background-color: #0078d4;
color: white;
border: none;
padding: 8px 16px;
}
QLineEdit {
border: 1px solid #cccccc;
border-radius: 4px;
padding: 4px;
}
```
### Class Selectors
```css
/* Match widgets with specific property */
QPushButton[primary="true"] {
background-color: #0078d4;
color: white;
}
QLabel[heading="true"] {
font-size: 24px;
font-weight: bold;
}
```
### ID Selectors
```css
/* Match specific widget by objectName */
#myButton {
background-color: red;
}
#statusLabel {
color: green;
}
```
### Pseudo-States
```css
/* Hover state */
QPushButton:hover {
background-color: #106ebe;
}
/* Pressed state */
QPushButton:pressed {
background-color: #005a9e;
}
/* Disabled state */
QPushButton:disabled {
background-color: #cccccc;
color: #666666;
}
/* Focus state */
QLineEdit:focus {
border: 2px solid #0078d4;
}
/* Checked state (for checkable widgets) */
QCheckBox:checked {
color: green;
}
/* Selected state */
QListWidget::item:selected {
background-color: #0078d4;
color: white;
}
```
## Applying Styles
### Application-Wide
```python
from PySide6.QtWidgets import QApplication
app = QApplication()
# Inline
app.setStyleSheet("""
QLabel { color: #333; }
QPushButton { padding: 5px 10px; }
""")
# From file
with open("style.qss", "r") as f:
app.setStyleSheet(f.read())
```
### Widget-Specific
```python
button = QPushButton("Styled")
button.setStyleSheet("""
QPushButton {
background-color: blue;
color: white;
border-radius: 5px;
}
QPushButton:hover {
background-color: darkblue;
}
""")
```
### Custom Properties
```python
# Set custom property
button = QPushButton("Primary")
button.setProperty("primary", True)
# Force style refresh
button.style().unpolish(button)
button.style().polish(button)
```
```css
/* Use in QSS */
QPushButton[primary="true"] {
background-color: #0078d4;
color: white;
}
QPushButton[primary="true"]:hover {
background-color: #106ebe;
}
```
## Common Properties
### Colors
```css
/* Text color */
color: #333333;
/* Background color */
background-color: white;
/* Selection colors */
selection-color: white;
selection-background-color: #0078d4;
/* Border color */
border: 1px solid #cccccc;
/* Alternate row color */
alternate-background-color: #f5f5f5;
```
### Fonts
```css
/* Font family */
font-family: "Segoe UI", Arial, sans-serif;
/* Font size */
font-size: 14px;
/* Font weight */
font-weight: bold; /* normal, bold, 100-900 */
/* Font style */
font-style: italic;
/* Combined */
font: bold 14px "Segoe UI";
```
### Borders
```css
/* All sides */
border: 1px solid #cccccc;
/* Individual sides */
border-top: 1px solid #cccccc;
border-right: 2px dashed #999999;
border-bottom: 1px solid #cccccc;
border-left: none;
/* Border radius */
border-radius: 4px;
/* Individual corners */
border-top-left-radius: 8px;
border-top-right-radius: 8px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
```
### Spacing
```css
/* Padding (inside border) */
padding: 10px;
padding: 10px 20px; /* vertical horizontal */
padding: 5px 10px 5px 10px; /* top right bottom left */
/* Margin (outside border) */
margin: 5px;
/* Spacing between widgets */
spacing: 10px;
```
### Size
```css
/* Minimum size */
min-width: 100px;
min-height: 30px;
/* Maximum size */
max-width: 500px;
max-height: 200px;
/* Fixed size */
width: 200px;
height: 50px;
```
## Widget-Specific Styles
### QPushButton
```css
QPushButton {
background-color: #0078d4;
color: white;
border: none;
border-radius: 4px;
padding: 8px 16px;
font-weight: bold;
}
QPushButton:hover {
background-color: #106ebe;
}
QPushButton:pressed {
background-color: #005a9e;
}
QPushButton:disabled {
background-color: #cccccc;
color: #666666;
}
/* Flat button */
QPushButton[flat="true"] {
background-color: transparent;
color: #0078d4;
border: 1px solid #0078d4;
}
```
### QLineEdit
```css
QLineEdit {
background-color: white;
border: 1px solid #cccccc;
border-radius: 4px;
padding: 4px 8px;
selection-background-color: #0078d4;
}
QLineEdit:focus {
border: 2px solid #0078d4;
}
QLineEdit:disabled {
background-color: #f5f5f5;
color: #999999;
}
/* Password field */
QLineEdit[echoMode="2"] {
lineedit-password-character: 9679; /* Unicode bullet */
}
```
### QComboBox
```css
QComboBox {
background-color: white;
border: 1px solid #cccccc;
border-radius: 4px;
padding: 4px 8px;
}
QComboBox:hover {
border-color: #999999;
}
QComboBox::drop-down {
border: none;
width: 24px;
}
QComboBox::down-arrow {
image: url(down_arrow.png);
width: 12px;
height: 12px;
}
/* Dropdown list */
QComboBox QAbstractItemView {
background-color: white;
border: 1px solid #cccccc;
selection-background-color: #0078d4;
}
```
### QTabWidget
```css
QTabWidget::pane {
border: 1px solid #cccccc;
border-radius: 4px;
}
QTabBar::tab {
background-color: #f5f5f5;
border: 1px solid #cccccc;
padding: 8px 16px;
margin-right: 2px;
}
QTabBar::tab:selected {
background-color: white;
border-bottom-color: white;
}
QTabBar::tab:hover {
background-color: #e5e5e5;
}
```
### QScrollBar
```css
/* Vertical scrollbar */
QScrollBar:vertical {
background-color: #f5f5f5;
width: 12px;
margin: 0;
}
QScrollBar::handle:vertical {
background-color: #cccccc;
border-radius: 6px;
min-height: 30px;
}
QScrollBar::handle:vertical:hover {
background-color: #999999;
}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical {
height: 0;
}
```
- ## Dark Theme Example
-
- ```python
- DARK_THEME = """
- /* Global */
- * {
- font-family: "Segoe UI", Arial, sans-serif;
- }
-
- QWidget {
- background-color: #1e1e1e;
- color: #e0e0e0;
- }
-
- /* Main window */
- QMainWindow {
- background-color: #1e1e1e;
- }
-
- /* Labels */
- QLabel {
- color: #e0e0e0;
- }
-
- /* Buttons */
- QPushButton {
- background-color: #0e639c;
- color: white;
- border: none;
- border-radius: 4px;
- padding: 6px 12px;
- font-weight: bold;
- }
-
- QPushButton:hover {
- background-color: #1177bb;
- }
-
- QPushButton:pressed {
- background-color: #0d5a8a;
- }
-
- QPushButton:disabled {
- background-color: #3c3c3c;
- color: #666666;
- }
-
- /* Input fields */
- QLineEdit, QTextEdit, QPlainTextEdit {
- background-color: #2d2d2d;
- color: #e0e0e0;
- border: 1px solid #3c3c3c;
- border-radius: 4px;
- padding: 4px 8px;
- selection-background-color: #0e639c;
- }
-
- QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {
- border-color: #0e639c;
- }
-
- /* ComboBox */
- QComboBox {
- background-color: #2d2d2d;
- color: #e0e0e0;
- border: 1px solid #3c3c3c;
- border-radius: 4px;
- padding: 4px 8px;
- }
-
- QComboBox:hover {
- border-color: #4a4a4a;
- }
-
- QComboBox::drop-down {
- border: none;
- width: 20px;
- }
-
- QComboBox QAbstractItemView {
- background-color: #2d2d2d;
- color: #e0e0e0;
- selection-background-color: #0e639c;
- border: 1px solid #3c3c3c;
- }
-
- /* SpinBox */
- QSpinBox, QDoubleSpinBox {
- background-color: #2d2d2d;
- color: #e0e0e0;
- border: 1px solid #3c3c3c;
- border-radius: 4px;
- padding: 4px;
- }
-
- /* Checkbox */
- QCheckBox {
- color: #e0e0e0;
- spacing: 8px;
- }
-
- QCheckBox::indicator {
- width: 16px;
- height: 16px;
- border: 1px solid #3c3c3c;
- border-radius: 3px;
- }
-
- QCheckBox::indicator:checked {
- background-color: #0e639c;
- border-color: #0e639c;
- }
-
- /* Radio button */
- QRadioButton {
- color: #e0e0e0;
- spacing: 8px;
- }
-
- QRadioButton::indicator {
- width: 16px;
- height: 16px;
- border: 1px solid #3c3c3c;
- border-radius: 8px;
- }
-
- QRadioButton::indicator:checked {
- background-color: #0e639c;
- border-color: #0e639c;
- }
-
- /* Tab widget */
- QTabWidget::pane {
- border: 1px solid #3c3c3c;
- background-color: #1e1e1e;
- }
-
- QTabBar::tab {
- background-color: #2d2d2d;
- color: #e0e0e0;
- border: 1px solid #3c3c3c;
- padding: 6px 12px;
- margin-right: 2px;
- }
-
- QTabBar::tab:selected {
- background-color: #1e1e1e;
- border-bottom-color: #1e1e1e;
- }
-
- QTabBar::tab:hover {
- background-color: #3c3c3c;
- }
-
- /* Scrollbar */
- QScrollBar:vertical {
- background-color: #2d2d2d;
- width: 12px;
- }
-
- QScrollBar::handle:vertical {
- background-color: #4a4a4a;
- border-radius: 6px;
- min-height: 30px;
- }
-
- QScrollBar::handle:vertical:hover {
- background-color: #5a5a5a;
- }
-
- QScrollBar::add-line:vertical,
- QScrollBar::sub-line:vertical {
- height: 0;
- }
-
- /* Scrollbar horizontal */
- QScrollBar:horizontal {
- background-color: #2d2d2d;
- height: 12px;
- }
-
- QScrollBar::handle:horizontal {
- background-color: #4a4a4a;
- border-radius: 6px;
- min-width: 30px;
- }
-
- QScrollBar::handle:horizontal:hover {
- background-color: #5a5a5a;
- }
-
- /* Menu */
- QMenuBar {
- background-color: #2d2d2d;
- color: #e0e0e0;
- }
-
- QMenuBar::item:selected {
- background-color: #0e639c;
- }
-
- QMenu {
- background-color: #2d2d2d;
- color: #e0e0e0;
- border: 1px solid #3c3c3c;
- }
-
- QMenu::item:selected {
- background-color: #0e639c;
- }
-
- /* Tooltip */
- QToolTip {
- background-color: #2d2d2d;
- color: #e0e0e0;
- border: 1px solid #3c3c3c;
- padding: 4px;
- }
-
- /* Status bar */
- QStatusBar {
- background-color: #007acc;
- color: white;
- }
-
- /* GroupBox */
- QGroupBox {
- border: 1px solid #3c3c3c;
- border-radius: 4px;
- margin-top: 12px;
- padding-top: 12px;
- font-weight: bold;
- }
-
- QGroupBox::title {
- subcontrol-origin: margin;
- left: 8px;
- padding: 0 4px;
- }
- """
+ ## Deep Dives
- # Apply
- app.setStyleSheet(DARK_THEME)
- ```
+ - **Dark Theme Example**: See [references/dark-theme.md](references/dark-theme.md) for a complete VS Code-inspired dark theme stylesheet.
## Best Practices
1. **Use semantic class names** - `primary`, `danger`, `warning`
2. **Organize styles by widget** - Keep related styles together
3. **Use variables** - Store colors in custom properties
4. **Test on all platforms** - Colors and fonts vary
5. **Use relative units** - `em` for fonts (limited support)
6. **Keep styles modular** - Separate files per theme
## References
- **Qt Style Sheets**: https://doc.qt.io/qtforpython-6/overviews/stylesheet.html
- **QSS Reference**: https://doc.qt.io/qtforpython-6/overviews/stylesheet-reference.html
- **Qt Examples**: https://doc.qt.io/qtforpython-6/overviews/stylesheet-examples.html
-