Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Change style sheet on the fly



  • This is the code of my QImprovedSlider class:

    // —› QImprovedSlider methods ‹—
    
    #include <QWidget>
    #include <QDebug>
    #include <QMouseEvent>
    #include <QStyleOptionSlider>
    
    #include "qimprovedslider.h"
    
    class DirectJump : public QProxyStyle
    {
    public:
        using QProxyStyle::QProxyStyle;
        int styleHint(QStyle::StyleHint hint, const QStyleOption* option = 0,
                      const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const
        {
            if (hint == SH_Slider_AbsoluteSetButtons)
                return (Qt::LeftButton);
            return QProxyStyle::styleHint(hint, option, widget, returnData);
        }
    
    };
    
    QImprovedSlider::QImprovedSlider(QWidget *parent) :
        QSlider(parent)
    {
        setStyleSheet(
                    "QSlider::groove:horizontal {"
                    "border: 1px solid #999999;"
                    "height: 5px;" /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */
                    "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);"
                    "border-radius: 3px;"
                    "}"
                    "QSlider::handle:horizontal {"
                    "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #81C097);"
                    "border: 1px solid #5c5c5c;"
                    "width: 16px;"
                    "margin: -2px 0;" /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
                    "border-radius: 3px;"
                    "}"
                    "QSlider::handle:horizontal:hover {"
                    "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #81C097);"
                    "border: 1px solid #808080;"
                    "width: 16px;"
                    "margin: -2px 0;" /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
                    "border-radius: 3px;"
                    "}"
                    "QSlider::add-page:horizontal {"
                    "background: #c0c0c0;"
                    "border-radius: 3px;"
                    "margin: 0 -1px;"
                    "}"
                    "QSlider::sub-page:horizontal {"
                    "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #81C097);"
                    "border-radius: 3px;"
                    "}"
                    );
        setStyle(new DirectJump);
    }
    
    void QImprovedSlider::mousePressEvent(QMouseEvent *event) {
        QStyleOptionSlider opt;
        initStyleOption(&opt);
        QRect sr = style()->subControlRect(QStyle::CC_Slider,
                                           &opt,
                                           QStyle::SC_SliderHandle,
                                           this);
        if (!sr.contains(event->pos()) && event->button() == Qt::LeftButton) {
            if (orientation() == Qt::Vertical)
                setValue(minimum() + ((maximum()-minimum()) * (height()-event->y())) / height() ) ;
            else
                setValue(minimum() + ((maximum()-minimum()) * event->x()) / width() ) ;
        }
        QSlider::mousePressEvent(event);
    }
    
    void QImprovedSlider::mouseReleaseEvent(QMouseEvent *event) {
        if (event->button() == Qt::LeftButton) {
            emit clicked(value());
            QSlider::mouseReleaseEvent(event);
        }
    }
    

    I would like to make sure that I can change its stylesheet on the fly: for that, I created a function using the QColorDialog. This is my attempt

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
    
        ui->setupUi(this);
    ...
    scrollbar = new QImprovedSlider(this);
    scrollbar->setGeometry(10,87,252,18);
    scrollbar->setOrientation(Qt::Horizontal);
    scrollbar->setMinimum(0);
    ...
    }
    
    void MainWindow::onTextColor()
    {
        QColor color = QColorDialog::getColor(Qt::blue, this );
            if( color.isValid() )
            {
              scrollbar->setStyleSheet( scrollbar->styleSheet().replace(QString("#81C097"), QString(color.name()), Qt::CaseInsensitive));
            }
    }
    

    Of course, this code doesn't work. Could you tell me where is wrong and if there are better methods to change the stylesheet on the fly?

    Thanks in advance


  • Lifetime Qt Champion

    @UnitScan said in Change style sheet on the fly:

    Of course, this code doesn't work

    Why not?

    scrollbar->setGeometry(10,87,252,18);

    running away and crying out loud



  • Please come back!
    @Christian-Ehrlicher said in Change style sheet on the fly:

    @UnitScan said in Change style sheet on the fly:

    Of course, this code doesn't work

    Why not?

    My scrollbar don't recolor after I pick up the new color via QColorDialog


  • Lifetime Qt Champion

    Hi,

    Are you sure your style sheet is correctly updated ?

    Note that with your techniqu, you will only be able to change it once.



  • @SGaist said in Change style sheet on the fly:

    Hi,

    Are you sure your style sheet is correctly updated ?

    Note that with your techniqu, you will only be able to change it once.

    That's what I'd like to know!
    Is there a better technique? If so, which one?


  • Lifetime Qt Champion

    Print the new style sheet.

    That said if you want to have something that you can change your should rather store your style sheet in a string and use the QString::arg method to generate the final version that you set on your widget.



  • @SGaist said in Change style sheet on the fly:

    Print the new style sheet.

    The one I get after running my replace command, or how should it be?


  • Lifetime Qt Champion

    @UnitScan said in Change style sheet on the fly:

    The one I get after running my replace command

    Yes, you can even print before and after...



  • Before:

                ```
                "QSlider::groove:horizontal {"
                "border: 1px solid #999999;"
                "height: 5px;" /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */
                "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);"
                "border-radius: 3px;"
                "}"
                "QSlider::handle:horizontal {"
                "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #81C097);"
                "border: 1px solid #5c5c5c;"
                "width: 16px;"
                "margin: -2px 0;" /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
                "border-radius: 3px;"
                "}"
                "QSlider::handle:horizontal:hover {"
                "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #81C097);"
                "border: 1px solid #808080;"
                "width: 16px;"
                "margin: -2px 0;" /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
                "border-radius: 3px;"
                "}"
                "QSlider::add-page:horizontal {"
                "background: #c0c0c0;"
                "border-radius: 3px;"
                "margin: 0 -1px;"
                "}"
                "QSlider::sub-page:horizontal {"
                "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #81C097);"
                "border-radius: 3px;"
                "}"
    
    
    
    
    After
    
                    ```
                     
                    "QSlider::groove:horizontal {"
                    "border: 1px solid #999999;"
                    "height: 5px;" /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */
                    "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #B1B1B1, stop:1 #c4c4c4);"
                    "border-radius: 3px;"
                    "}"
                    "QSlider::handle:horizontal {"
                    "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #0000f0);"
                    "border: 1px solid #5c5c5c;"
                    "width: 16px;"
                    "margin: -2px 0;" /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
                    "border-radius: 3px;"
                    "}"
                    "QSlider::handle:horizontal:hover {"
                    "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #FFFFFF, stop:1 #0000f0);"
                    "border: 1px solid #808080;"
                    "width: 16px;"
                    "margin: -2px 0;" /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
                    "border-radius: 3px;"
                    "}"
                    "QSlider::add-page:horizontal {"
                    "background: #c0c0c0;"
                    "border-radius: 3px;"
                    "margin: 0 -1px;"
                    "}"
                    "QSlider::sub-page:horizontal {"
                    "background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #b4b4b4, stop:1 #0000f0);"
                    "border-radius: 3px;"
                    "}"
    

    #81C097 is replaced with #0000f0, where #0000f0 is a color chosen via QColorDialog


  • Lifetime Qt Champion

    Then use the unpolish/polish QStyle trick.


Log in to reply