I'd like the handle of the slider to go from blue to yellow. When set on the left, it's blue; and when you move it to the right, it will have a gradient from blue to yellow.
If it is possible through style sheets, how? And if not, how can I implement that in the paintEvent of a subclass of QSlider?
Actually you don't really have to do anything fancy, the stock QSlider
already has the valueChanged(int)
signal, so you can connect that to a function which mixes between the two colors based on the position and sets the style color. Here is a minimal example:
static QColor operator+(const QColor & a, const QColor & b) {
return QColor(a.red() + b.red(), a.green() + b.green(), a.blue() + b.blue());
}
static QColor operator*(const QColor & c, const qreal r) {
return QColor(c.red() * r, c.green() * r, c.blue() * r);
}
class Widget : public QWidget {
Q_OBJECT
public:
Widget(QWidget *parent = 0) : QWidget(parent), from(248, 181, 20), to(64, 150, 214) {
auto l = new QHBoxLayout(this);
setLayout(l);
s = new QSlider(Qt::Horizontal, this);
s->setMinimum(0);
s->setMaximum(100);
l->addWidget(s);
connect(s, &QSlider::valueChanged, this, &Widget::colorize);
colorize(s->value());
}
private:
void colorize(int v) {
int d = s->maximum() - s->minimum();
v = v - s->minimum();
qreal rv = qreal(v) / d;
QColor c = from * rv + to * (1.0 - rv);
s->setStyleSheet(QString("QSlider::handle:horizontal {background-color: %1;}").arg(c.name()));
}
QSlider * s;
QColor from, to;
};
This will work for any slider range and orientation, the code basically finds the relative handle position in range 0.0 to 1.0 and uses that to mix the from
and to
colors to set the handle color to the respective value. Oddly enough, QColor
didn't have the operators to multiply and add, which can come quite in handy.
Additionally, instead of mixing between two colors you can construct a color in HSL format, which will give you a slightly different gradient. Changing from/to
from QColor
to hues 42 and 202 respectively, you can then:
QColor c = QColor::fromHsl(205 - (205 - 42) * rv, 200, 135);
This will give you a color sweep for the hue rather than mix between two fixed colors, which may be more applicable in the context of temperature:
Note that now in the middle you get a cyan-ish color rather than "zombie" green and you get through clean green before you get to orange.