Changing colors of the QSlider



  • I have two horizontal QSliders and I would like it so that when the user moves the QSlider, it changes color based on the location of the QSlider. There will be three ranges: red for the first 1/3 of the QSlider, yellow for the second 1/3 of the QSlider and the last 1/3 will be green. I am able to show the colors BUT since I used the stylesheet, the ticks that I enabled in order to show where each range is, disappears. I did some research and I saw that you needed to subclass QSlider and use paintevent in order to add the ticks. However, I have tried the following and nothing happens.

    What I have on the .ui file are the 2 QSliders inside a QFrame and the QFrame's stylesheet contains:

    QSlider::groove:horizontal {
    border: 1px solid #bbb;```
    
    height: 10px;
    border-radius: 4px;
    }
    
    QSlider::sub-page:horizontal {
    border: 1px solid #777;
    height: 10px;
    border-radius: 4px;
    }
    
    QSlider::add-page:horizontal {
    background: white;
    border: 1px solid #777;
    height: 10px;
    border-radius: 4px;
    }
    
    QSlider::handle:horizontal {
    background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
        stop:0 #eee, stop:1 #ccc);
    border: 1px solid #777;
    width: 4px;
    margin-top: -2px;
    margin-bottom: -2px;
    border-radius: 4px;
    }
    

    form.h file

    #ifndef FORM_H
    #define FORM_H
    
    #include <QWidget>
    #include <QSlider>
    
    namespace Ui {
    class Form;
    }
    
    class Form : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Form(QWidget *parent = 0);
        ~Form();
    
    public slots:
        void updateValue(int value);
        void updateValue2(int value);
    
    private:
        Ui::Form *ui;
    };
    

    form.cpp

    #include "form.h"
    #include "ui_form.h"
    #include <QDebug>
    #include "myslider.h"
    
    Form::Form(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Form)
    {
        ui->setupUi(this);
        int x = 99/3;
    
        ui->horizontalSlider = new MySlider();
       ui->horizontalSlider_2  = new MySlider();
    
        ui->horizontalSlider->setTickInterval(x);
        ui->horizontalSlider_2->setTickInterval(x);
    
        connect(ui->horizontalSlider, SIGNAL(valueChanged(int)),this,SLOT(updateValue(int)));
        connect(ui->horizontalSlider_2, SIGNAL(valueChanged(int)),this,SLOT(updateValue2(int)));
    }
    
    
    void Form::updateValue(int value)
    {
        if(value < 40)
        {
            ui->horizontalSlider->setStyleSheet("QSlider::sub-page:horizontal {background: red;}");
        }
        else if(value >=40 && value < 60)
        {
            ui->horizontalSlider->setStyleSheet("QSlider::sub-page:horizontal {background: yellow;}");
        }
        else
        {
            ui->horizontalSlider->setStyleSheet("QSlider::sub-page:horizontal {background: green;}");
        }
    }
    
    void Form::updateValue2(int value)
    {
    
        if(value < 40)
        {
            ui->horizontalSlider_2->setStyleSheet("QSlider::sub-page:horizontal {background: red;}");
        }
        else if(value >=40 && value < 60)
        {
            ui->horizontalSlider_2->setStyleSheet("QSlider::sub-page:horizontal {background: yellow;}");
        }
        else
        {
            ui->horizontalSlider_2->setStyleSheet("QSlider::sub-page:horizontal {background: green;}");
        }
    }
    
    Form::~Form()
    {
        delete ui;
    }
    
    

    myslider.h

    #ifndef MYSLIDER_H
    #define MYSLIDER_H
    
    #include <QWidget>
    #include <QSlider>
    
    class MySlider : public QSlider
    {
        Q_OBJECT
    public:
        MySlider(QWidget *parent = 0);
    
    protected:
        void paintEvent(QPaintEvent *ev);
    
    };
    
    #endif // MYSLIDER_H
    

    myslider.cpp

    #include "myslider.h"
    #include <QStylePainter>
    #include <QStyleOptionSlider>
    #include <QDebug>
    #include <QSlider>
    
    MySlider::MySlider(QWidget *parent) :
        QSlider(parent)
    {
    }
    
    void MySlider::paintEvent(QPaintEvent *ev)
    {
        QSlider::paintEvent(ev);
    
        QStylePainter p(this);
        QStyleOptionSlider opt;
        initStyleOption(&opt);
    
        QRect handle = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
     ;
        // draw tick marks
        // do this manually because they are very badly behaved with style sheets
        int interval = tickInterval();
    
        if (interval == 0)
        {
            interval = pageStep();
        }
    
        if (tickPosition() != NoTicks)
        {
    
            for (int i = minimum(); i <= maximum(); i += interval)
            {
                int x = qRound((double)((double)((double)(i - this->minimum()) / (double)(this->maximum() - this->minimum())) * (double)(this->width() - handle.width()) + (double)(handle.width() / 2.0))) - 1;
                int h = 4;
                p.setPen(QColor("#a5a294"));
                if (tickPosition() == TicksBothSides || tickPosition() == TicksAbove)
                {
                    int y = this->rect().top();
                    p.drawLine(x, y, x, y + h);
                }
                if (tickPosition() == TicksBothSides || tickPosition() == TicksBelow)
                {
                    int y = this->rect().bottom();
                    p.drawLine(x, y, x, y - h);
                }
    
            }
        }
    
        // draw the slider (this is basically copy/pasted from QSlider::paintEvent)
        opt.subControls = QStyle::SC_SliderGroove;
        p.drawComplexControl(QStyle::CC_Slider, opt);
    
        // draw the slider handle
        opt.subControls = QStyle::SC_SliderHandle;
        p.drawComplexControl(QStyle::CC_Slider, opt);
    
    }
    
    


  • I figured out the answer. I have to create a QSlider from scratch meaning not one created from the ui already.

    So,

        QSlider *slider = new MySlider(Qt::horizontal);
        ui->frameTestLayout->addWidget(slider);
        slider->setFocusPolicy(Qt::NoFocus);
        slider->setTickPosition(QSlider::TicksAbove);
        slider->setTickInterval(number);
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.