Dynamic Button Styling in Qt with QSS

In many application development scenarios, there's a common requirement to change a button's appearance based on different application states or logic.

Approach 1: Directly Setting Stylesheets in Code

The most straightforward method is to call setStyleSheet() whenever the button's state changes. This approach is simple but can lead to code duplication and makes styling difficult to manage centrally.

// Set style for the normal state
myButton->setStyleSheet("QPushButton { background-color: #27a9e3; }"
                       "QPushButton:hover { background-color: #66c011; }"
                       "QPushButton:pressed { background-color: yellow; }");

// Set style for the selected state
myButton->setStyleSheet("QPushButton { background-color: red; }");

Approach 2: Using QSS Property Selectors

A more organized approach involves defining all possible styles in a separate QSS file and then switching between them by setting or unsetting a custom property on the widget. This separates the presentation (styles) from the logic.

First, define the styles in a .qss file, including a custom property selector:

/* Default button style */
QPushButton {
    color: white;
    background-color: #27a9e3;
    border-width: 0px;
    border-radius: 3px;
}

/* Hover state */
QPushButton:hover {
    color: white;
    background-color: #66c011;
    border-width: 0px;
    border-radius: 3px;
}

/* Pressed state */
QPushButton:pressed {
    color: white;
    background-color: yellow;
    border-width: 0px;
    border-radius: 3px;
}

/* Custom 'active' state, triggered by the 'pagematches' property */
QPushButton[pagematches="true"] {
    color: white;
    background-color: red;
    border-width: 0px;
    border-radius: 3px;
}

Next, load this stylesheet and implement the logic to change the button's state by modifying its properties:

#include <QVariant>

// A helper function to update a widget's style based on a property change
void updateWidgetStyle(QWidget *widget, const QString &property, const QVariant &value) {
    if (!widget) {
        return;
    }
    widget->setProperty(property.toLatin1().constData(), value);
    widget->style()->unpolish(widget); // Unapply the old style
    widget->style()->polish(widget);   // Reapply the style with the new property
    widget->update();                 // Trigger a repaint
}

// Example slot to handle a state change, e.g., from a QStackedWidget's index change
void handleStackIndexChanged(int index) {
    // First, reset all buttons to the default state
    updateWidgetStyle(buttonA, "pagematches", false);
    updateWidgetStyle(buttonB, "pagematches", false);
    updateWidgetStyle(buttonC, "pagematches", false);

    // Then, set the active button based on the new index
    switch (index) {
        case 0:
            updateWidgetStyle(buttonA, "pagematches", true);
            break;
        case 1:
            updateWidgetStyle(buttonB, "pagematches", true);
            break;
        // Add more cases for other indices as needed
    }
}

This second method centralizes styling in a .qss file, making it much easier to maintain and modify. As the application matures, this approach also facilitates more advanced features like dynamic theming by loading different QSS files at runtime.

Tags: Qt QSS C++

Posted on Wed, 19 Aug 2026 16:06:51 +0000 by BluePhoenixNC