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);