Of course! Let's dive deep into QPalette in Python, specifically in the context of the PyQt or PySide libraries.

What is a QPalette?
In simple terms, a QPalette is a collection of colors that defines the look-and-feel of a widget. Think of it as a painter's palette for your user interface. It tells each widget which color to use for different parts, like the background, foreground (text), buttons, and more.
Every widget in Qt has a QPalette. When you create a widget, it inherits its palette from its parent, and ultimately from the application's default palette. This is what gives your application its native look on different operating systems (Windows, macOS, Linux).
The Core Concept: Color Roles
A QPalette doesn't just hold a few random colors. It organizes them into Color Roles. Each role has a specific meaning. The most common ones are:
Window: The general background color for a widget (e.g., the background of aQLabelorQTextEdit).WindowText: The foreground color for text used on top of theWindowcolor (e.g., the text color of aQLabel).Base: The background color forQLineEdit,QTextEdit, and other items that accept input or display text.Text: The foreground color for text in widgets likeQLineEditorQTextEdit.Button: The background color for a button (QPushButton).ButtonText: The color of the text on a button.Highlight: The background color for selected items (e.g., selected text in aQTextEditor a selected row in aQTableWidget).HighlightedText: The color of the text over aHighlightbackground.
Two Important States: Active and Inactive
A QPalette manages colors for two distinct states of an application:

QPalette.Active: This state applies to the widget that currently has keyboard focus (the "active" widget). For example, if you click on oneQPushButton, it becomes active.QPalette.Inactive: This state applies to all other widgets that do not have focus. For example, other buttons on the window are "inactive".
This distinction is crucial for providing good user feedback. Typically, the active widget might have a slightly brighter or more saturated color to draw the user's attention.
A QPalette also has a QPalette.Disabled state, which is used when a widget is disabled (e.g., setEnabled(False)).
Practical Examples
Let's see how to use QPalette in code. We'll use PyQt6 for these examples, but the code is nearly identical for PyQt5 and PySide6.
Example 1: Changing the Background of a Widget
This is the most common use case. We'll change the background of a QLabel.

import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QWidget, QVBoxLayout
from PyQt6.QtGui import QPalette, QColor
from PyQt6.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("QPalette Example")
self.setGeometry(100, 100, 400, 200)
# Create a central widget and a layout
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
# Create a label
self.label = QLabel("This is a label with a custom background.")
self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(self.label)
# --- Apply the palette ---
self.apply_palette()
def apply_palette(self):
# 1. Get the current palette of the widget
palette = self.label.palette()
# 2. Define the new color
new_color = QColor("#4CAF50") # A nice green
# 3. Set the color for the 'Window' role
# The 'Window' role is used for the background of most widgets.
palette.setColor(QPalette.ColorRole.Window, new_color)
# 4. Set the color for the 'WindowText' role (text color)
# We need to ensure the text is readable on the new background.
palette.setColor(QPalette.ColorRole.WindowText, QColor("white"))
# 5. Set the modified palette back to the widget
self.label.setPalette(palette)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
Example 2: Changing the Application's Global Palette
If you want to change the look of your entire application, you should modify the palette of the entire QApplication.
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton, QWidget, QVBoxLayout
from PyQt6.QtGui import QPalette, QColor
from PyQt6.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Global Palette Example")
self.setGeometry(100, 100, 300, 200)
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
self.button1 = QPushButton("Button 1")
self.button2 = QPushButton("Button 2")
self.label = QLabel("A label")
layout.addWidget(self.button1)
layout.addWidget(self.button2)
layout.addWidget(self.label)
# --- Main execution ---
if __name__ == "__main__":
app = QApplication(sys.argv)
# --- Modify the application's default palette ---
palette = app.palette()
# Set a dark background for the whole application
palette.setColor(QPalette.ColorRole.Window, QColor(53, 53, 53))
# Set light text for the window
palette.setColor(QPalette.ColorRole.WindowText, QColor(255, 255, 255))
# Set a slightly lighter color for buttons
palette.setColor(QPalette.ColorRole.Button, QColor(70, 70, 70))
# Set text color for buttons
palette.setColor(QPalette.ColorRole.ButtonText, QColor(255, 255, 255))
# Set highlight color for selections
palette.setColor(QPalette.ColorRole.Highlight, QColor(142, 45, 197))
palette.setColor(QPalette.ColorRole.HighlightedText, QColor(0, 0, 0))
# Apply the palette to the entire application
app.setPalette(palette)
# Create and show the main window
window = MainWindow()
window.show()
sys.exit(app.exec())
In this example, all standard widgets (QPushButton, QLabel, etc.) will inherit this dark theme from the application's palette.
Example 3: Using Different Color Roles (Base vs Window)
This example highlights the difference between the Window and Base roles.
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QTextEdit, QLabel, QWidget, QVBoxLayout
from PyQt6.QtGui import QPalette, QColor
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Base vs Window Role")
self.setGeometry(100, 100, 400, 300)
central_widget = QWidget()
self.setCentralWidget(central_widget)
layout = QVBoxLayout(central_widget)
self.label = QLabel("This label uses the 'Window' role for its background.")
self.text_edit = QTextEdit("This text edit uses the 'Base' role for its background.")
layout.addWidget(self.label)
layout.addWidget(self.text_edit)
self.apply_specific_palette()
def apply_specific_palette(self):
palette = self.palette() # Get the application's palette to start with
# --- Set colors for different roles ---
# 'Window' is for general backgrounds (like QLabel)
palette.setColor(QPalette.ColorRole.Window, QColor(100, 100, 200)) # Blue
# 'WindowText' is for text over the 'Window' color
palette.setColor(QPalette.ColorRole.WindowText, QColor(255, 255, 255)) # White
# 'Base' is for input fields and text widgets
palette.setColor(QPalette.ColorRole.Base, QColor(50, 50, 50)) # Dark Grey
# 'Text' is for text over the 'Base' color
palette.setColor(QPalette.ColorRole.Text, QColor(200, 255, 200)) # Light Green
# Apply the new palette to the entire window
self.setPalette(palette)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
When you run this, you'll see the QLabel has a blue background, while the QTextEdit has a dark grey background, demonstrating how different roles are used by different types of widgets.
Summary
| Concept | Description | Example |
|---|---|---|
QPalette |
An object that holds a set of colors for a widget or application. | palette = my_widget.palette() |
| Color Role | The semantic meaning of a color (e.g., background, text, button). | palette.setColor(QPalette.ColorRole.Window, QColor("blue")) |
QPalette.Active |
Colors for the widget that currently has keyboard focus. | palette.setColor(QPalette.ColorGroup.Active, ...) |
QPalette.Inactive |
Colors for widgets that do not have focus. | palette.setColor(QPalette.ColorGroup.Inactive, ...) |
| Application Palette | The default palette for all widgets in the app. | app.setPalette(palette) |
Mastering QPalette is key to creating consistent, themable, and visually appealing applications with PyQt/PySide.
