I'm trying to set the background color of a widget to a "default" system color using
setStyleSheet(). I don't want to hard-code a specific color, because if the user changes their color scheme it could look weird or unreadable. Is there a set of default colors provided by the chosen color scheme?
This comes up often when you start customizing the appearance of your widgets. Hard-coding colors like #ffffff or lightgray into your stylesheets works fine on your machine, but the moment someone with a dark theme or a custom color scheme runs your app, things can look out of place — or worse, unreadable.
The good news is that Qt gives you access to the system's current color palette, so you can pull colors directly from the user's active theme and use them wherever you need.
The QPalette: Your Gateway to System Colors
Every Qt application has a palette — a QPalette object that holds all the colors the system (or the current style) uses to draw widgets. This includes things like the default window background, text color, button color, highlighted text, and more.
You can access the application's palette at any time like this:
palette = self.palette()
Or from anywhere in your application:
from PyQt6.QtWidgets import QApplication
palette = QApplication.instance().palette()
The palette organizes colors into roles. Each role describes what a color is used for. Some commonly useful roles include:
| Role | Description |
|---|---|
QPalette.ColorRole.Window |
Default background color for windows |
QPalette.ColorRole.WindowText |
Default text color |
QPalette.ColorRole.Base |
Background color for text entry widgets |
QPalette.ColorRole.AlternateBase |
Alternate background color (e.g., for alternating row colors in lists) |
QPalette.ColorRole.Button |
Background color for buttons |
QPalette.ColorRole.Highlight |
Background color for selected items |
QPalette.ColorRole.HighlightedText |
Text color for selected items |
Getting a Color from the Palette
To retrieve a specific color, call .color() on the palette and pass in the role you want:
from PyQt6.QtGui import QPalette
palette = self.palette()
color = palette.color(QPalette.ColorRole.AlternateBase)
This gives you a QColor object. To use it in a stylesheet, you can convert it to a string with .name(), which returns a hex color code like #e7e7e7:
color_hex = color.name() # e.g. "#e7e7e7"
Using Palette Colors in Stylesheets
Now you can combine these pieces to build a stylesheet that uses the system's own colors:
palette = self.palette()
alt_base = palette.color(QPalette.ColorRole.AlternateBase).name()
self.line_edit.setStyleSheet(
f"QLineEdit {{ background: {alt_base}; }}"
)
Because you're reading the color from the palette at runtime, the stylesheet will always match the user's current color scheme — whether they're using a light theme, a dark theme, or something completely custom.
A Complete Working Example
Here's a small application that demonstrates reading several palette colors and applying one to a QLineEdit background. It also displays a few of the current system colors so you can see what's available.
import sys
from PyQt6.QtGui import QPalette
from PyQt6.QtWidgets import (
QApplication,
QFormLayout,
QLabel,
QLineEdit,
QVBoxLayout,
QWidget,
)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("System Palette Colors")
layout = QVBoxLayout()
self.setLayout(layout)
# Create a QLineEdit styled with the system's AlternateBase color.
palette = self.palette()
alt_base = palette.color(QPalette.ColorRole.AlternateBase).name()
self.line_edit = QLineEdit()
self.line_edit.setPlaceholderText(
f"Background set to AlternateBase ({alt_base})"
)
self.line_edit.setStyleSheet(
f"QLineEdit {{ background: {alt_base}; }}"
)
layout.addWidget(self.line_edit)
# Show a reference of current palette colors.
form = QFormLayout()
layout.addLayout(form)
roles = {
"Window": QPalette.ColorRole.Window,
"WindowText": QPalette.ColorRole.WindowText,
"Base": QPalette.ColorRole.Base,
"AlternateBase": QPalette.ColorRole.AlternateBase,
"Button": QPalette.ColorRole.Button,
"Highlight": QPalette.ColorRole.Highlight,
"HighlightedText": QPalette.ColorRole.HighlightedText,
}
for name, role in roles.items():
color = palette.color(role)
color_hex = color.name()
swatch = QLabel(f" {color_hex} ")
swatch.setStyleSheet(
f"background: {color_hex}; "
f"color: {'white' if color.lightness() < 128 else 'black'}; "
f"padding: 4px; "
f"border: 1px solid gray;"
)
form.addRow(name, swatch)
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
Run this and you'll see your QLineEdit with a background that matches the system's alternate base color, along with a set of color swatches showing the current palette values. If you change your system theme and run it again, the colors will update automatically.
An Alternative: Skip the Stylesheet Entirely
If you only need to change the background (or foreground) color of a single widget, you can skip stylesheets altogether and modify the widget's palette directly:
palette = self.line_edit.palette()
palette.setColor(
QPalette.ColorRole.Base,
palette.color(QPalette.ColorRole.AlternateBase),
)
self.line_edit.setPalette(palette)
This sets the QLineEdit's own Base color (which controls its background) to the system's AlternateBase color — no stylesheet needed. This approach is lighter-weight and avoids some of the quirks that stylesheets can introduce with certain styles.
Handling Colors with Alpha Transparency
Some palette colors include an alpha (transparency) component. The .name() method returns only the RGB hex value by default (e.g., #e7e7e7), discarding any transparency information. If you need to preserve alpha, pass QColor.NameFormat.HexArgb:
from PyQt6.QtGui import QColor
color = palette.color(QPalette.ColorRole.Highlight)
color_with_alpha = color.name(QColor.NameFormat.HexArgb) # e.g. "#ff3daee9"
You can use this in stylesheets with the rgba() function instead, which tends to be more readable:
color = palette.color(QPalette.ColorRole.Highlight)
rgba = f"rgba({color.red()}, {color.green()}, {color.blue()}, {color.alpha()})"
self.widget.setStyleSheet(f"background: {rgba};")
For most palette colors the alpha is fully opaque (255), so .name() alone will work perfectly well.
When to Use Each Approach
Both approaches — stylesheets with palette colors and direct palette modification — have their place:
- Stylesheets with palette colors are great when you need to combine system colors with other stylesheet features like borders, padding, or pseudo-state selectors (
:hover,:pressed, etc.). - Direct palette modification is simpler when all you need is a background or text color change on a specific widget, and you don't need any other stylesheet features.
Whichever approach you choose, reading from the palette means your app will stay consistent with the user's desktop theme — and that's a much better experience than hard-coded colors that clash with everything else on screen.
PyQt/PySide Office Hours 1:1 with Martin Fitzpatrick
Save yourself time and frustration. Get one on one help with your projects. Bring issues, bugs and questions about usability to architecture and maintainability, and leave with solutions.