¿Es posible cambiar el color de un asa QSlider según su posición?

Entendí bastante bien cómo personalizar un QSlider a través de hojas de estilo, pero me pregunto si es posible hacer lo siguiente:

introduzca la descripción de la imagen aquí

Me gustaría que el control del control deslizante pase de azul a amarillo. Cuando se pone a la izquierda, es azul; y cuando lo muevas a la derecha, tendrá un degradado de azul a amarillo.

Si es posible a través de las hojas de estilo, ¿cómo? Y si no, ¿cómo puedo implementar eso en el paintEvent de una subclase de un QSlider?

En realidad, no tiene que hacer nada sofisticado, el QSlider original ya tiene la valueChanged(int) , por lo que puede conectarlo a una función que mezcla entre los dos colores según la posición y establece el color del estilo. Aquí hay un ejemplo mínimo:

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

Esto funcionará para cualquier rango y orientación del control deslizante, el código básicamente encuentra la posición relativa del controlador en el rango de 0.0 a 1.0 y lo utiliza para mezclar los colores from y para establecer el color del mango en el valor respectivo. Por extraño que parezca, QColor no tuvo a los operadores para multiplicar y agregar, lo que puede ser muy útil.

introduzca la descripción de la imagen aquí

Además, en lugar de mezclar entre dos colores, puede construir un color en formato HSL, lo que le dará un gradiente ligeramente diferente. Al cambiar from/to de QColor a tonos 42 y 202 respectivamente, puede:

 QColor c = QColor::fromHsl(205 - (205 - 42) * rv, 200, 135); 

Esto le dará un barrido de color para el tono en lugar de mezclar entre dos colores fijos, que pueden ser más aplicables en el contexto de la temperatura:

introduzca la descripción de la imagen aquí

Tenga en cuenta que ahora, en el medio, obtiene un color cian-ish en lugar de verde “zombie” y obtiene un verde limpio antes de llegar al naranja.

No creo que puedas hacer esto usando una hoja de estilo simple. Pero eso se puede hacer fácilmente especializando la clase QSlider y aplicando una hoja de estilo apropiada cuando el usuario mueve el cursor (es decir, cuando se emite valueChanged).

Aquí hay una clase que escribí que hace el truco. Funciona para el cursor horizontal y vertical y se puede personalizar para usar cualquier color. Crea una QImage desde un QLinearGradient para almacenar el mapa de color degradado, luego, cuando cambia el valor del control deslizante, extrae el color apropiado de la imagen en función de la posición del control deslizante y lo aplica a través de una hoja de estilo.

Intenté hacer que la clase fuera genérica para su reutilización, pero podría simplificarse si no necesita personalizar los colores y solo usar los controles deslizantes horizontales.

gradientslider.h:

 #include  #include  #include  class GradientSlider : public QSlider { Q_OBJECT public: GradientSlider( QColor from, QColor to, Qt::Orientation orientation, QWidget* parent ); private slots: void changeColor( int ); private: QImage gradient; }; 

gradientslider.cpp:

 #include "gradientslider.h" #include  #include  GradientSlider::GradientSlider( QColor from, QColor to, Qt::Orientation orientation, QWidget* parent ) : QSlider( orientation, parent ), gradient( QSize(100,100), QImage::Format_RGB32 ) { // create linear gradient QLinearGradient linearGrad( QPointF(0, 0), (orientation==Qt::Horizontal) ? QPointF(100, 0) : QPointF(0, 100) ); linearGrad.setColorAt(0, from); linearGrad.setColorAt(1, to); // paint gradient in a QImage: QPainter p(&gradient); p.fillRect(gradient.rect(), linearGrad); connect( this, SIGNAL(valueChanged(int)), this, SLOT(changeColor(int)) ); // initialize changeColor( value() ); } void GradientSlider::changeColor( int pos ) { QColor color; if ( orientation() == Qt::Horizontal ) { // retrieve color index based on cursor position int posIndex = gradient.size().width() * ( pos - minimum() ) / (maximum() - minimum()); posIndex = std::min( posIndex, gradient.width() - 1 ); // pickup appropriate color color = gradient.pixel( posIndex, gradient.size().height()/2 ); } else { // retrieve color index based on cursor position int posIndex = gradient.size().height() * ( pos - minimum() ) / (maximum() - minimum()); posIndex = std::min( posIndex, gradient.height() - 1 ); // pickup appropriate color color = gradient.pixel( gradient.size().width()/2, posIndex ); } // create and apply stylesheet! // can be customized to change background and handle border! setStyleSheet( "QSlider::handle:" + (( orientation() == Qt::Horizontal ) ? QString("horizontal"):QString("vertical")) + "{ \ border-radius: 5px; \ border: 2px solid #FFFFFF; \ width: 20px; \ margin: -5px 0; \ background: " + color.name() + "}" ); } 

Ahora solo haz:

 QHBoxLayout* layout = new QHBoxLayout( this ); // horizontal slider: layout->addWidget( new GradientSlider( QColor(79,174,231), QColor(251,192,22), Qt::Horizontal, this ) ); // or, vertical slider: layout->addWidget( new GradientSlider( QColor(79,174,231), QColor(251,192,22), Qt::Vertical, this ) ); 

Los colores QColor(79,174,231) (~ azul) y QColor(251,192,22) (~ amarillo) se seleccionaron de la imagen en la publicación de la pregunta original y se pueden reemplazar por Qt::blue , Qt::yellow (que termina ligeramente diferente coloración).

Esto lo hará:

introduzca la descripción de la imagen aquí introduzca la descripción de la imagen aquí introduzca la descripción de la imagen aquí