Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Coloring slider handle depending on state

Coloring slider handle depending on state

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 3 Posters 638 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    ian28
    wrote on last edited by ian28
    #1

    I have a custom slider widget class that inherits from QSlider. The slider has an internal state that is set by the application. I want to color the sliders handle depending on that state. I also created a QProxyStyle which this widget uses that modifies the handles rect. The base style is fusion. I tried to copy paste the drawing of the handle from the fusion style into the proxy but I dont understand how to include the private qt classes this style is using. Probably its not required to do this at all. How can I change the handles color without affecting other components of the slider?

    JoeCFDJ 1 Reply Last reply
    0
    • I ian28

      I have a custom slider widget class that inherits from QSlider. The slider has an internal state that is set by the application. I want to color the sliders handle depending on that state. I also created a QProxyStyle which this widget uses that modifies the handles rect. The base style is fusion. I tried to copy paste the drawing of the handle from the fusion style into the proxy but I dont understand how to include the private qt classes this style is using. Probably its not required to do this at all. How can I change the handles color without affecting other components of the slider?

      JoeCFDJ Offline
      JoeCFDJ Offline
      JoeCFD
      wrote on last edited by
      #2

      @ian28 I guess you can use style sheet to do it.
      https://doc.qt.io/qt-6/stylesheet-examples.html

      I 1 Reply Last reply
      0
      • JoeCFDJ JoeCFD

        @ian28 I guess you can use style sheet to do it.
        https://doc.qt.io/qt-6/stylesheet-examples.html

        I Offline
        I Offline
        ian28
        wrote on last edited by
        #3

        @JoeCFD Do stylesheets support custom states that are based on some values of my custom slider or do i have to update the stylesheet at runtime?

        JoeCFDJ 1 Reply Last reply
        0
        • I Offline
          I Offline
          ian28
          wrote on last edited by
          #4

          This topic describes the same problem link. The marked answer suggests to either derive from QStyleOption or directly query the widget. This is what i tried by copy pasting the drawing of the slider of the fusion style and only modify the background by either querying the widget or using a subclass of the StyleOptionslider. However the fusion style uses private qt classes, how can I include them?

          #if QT_CONFIG(slider)
              case CC_Slider:
                  if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(
          option)) {
                      QRect groove = proxy()->subControlRect(CC_Slider, option, 
          SC_SliderGroove, widget);
                      QRect handle = proxy()->subControlRect(CC_Slider, option, 
          SC_SliderHandle, widget);
                      bool horizontal = slider->orientation == Qt::Horizontal;
                      bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
                      bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
                      QColor activeHighlight = d->highlight(
          option->palette);
                      QPixmap cache;
                      QBrush oldBrush = painter->brush();
                      QPen oldPen = painter->pen();
                      QColor shadowAlpha(Qt::black);
                      shadowAlpha.setAlpha(10);
                      if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
                          outline = d->highlightedOutline(
          option->palette);
                      if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
                          QColor grooveColor;
                          grooveColor.setHsv(
          buttonColor.hue(),
                                             qMin(255, 
          (int)(buttonColor.saturation())),
                                             qMin(255, 
          (int)(buttonColor.value()*0.9)));
                          QString groovePixmapName = QStyleHelper::uniqueName("slider_groove"_L1, option, 
          groove.size());
                          QRect pixmapRect(0, 0, groove.width(), groove.height());
                          // draw background groove
                          if (!QPixmapCache::find(groovePixmapName, 
          &cache)) {
                              cache = styleCachePixmap(
          pixmapRect.size());
                              cache.fill(
          Qt::transparent);
                              QPainter groovePainter(&cache);
                              groovePainter.setRenderHint(QPainter::Antialiasing, 
          true);
                              groovePainter.translate(0.5, 
          0.5);
                              QLinearGradient gradient;
                              if (horizontal) {
                                  gradient.setStart(pixmapRect.center().x(), 
          pixmapRect.top());
                                  gradient.setFinalStop(pixmapRect.center().x(), 
          pixmapRect.bottom());
                              }
                              else {
                                  gradient.setStart(pixmapRect.left(), 
          pixmapRect.center().y());
                                  gradient.setFinalStop(pixmapRect.right(), 
          pixmapRect.center().y());
                              }
                              groovePainter.setPen(QPen(outline));
                              gradient.setColorAt(0, grooveColor.darker(
          110));
                              gradient.setColorAt(1, grooveColor.lighter(
          110));//palette.button().color().darker(115));
                              groovePainter.setBrush(gradient);
                              groovePainter.drawRoundedRect(pixmapRect.adjusted(1, 1, -2, -2), 1, 
          1);
                              groovePainter.end();
                              QPixmapCache::insert(groovePixmapName, 
          cache);
                          }
                          painter->drawPixmap(groove.topLeft(), 
          cache);
                          // draw blue groove highlight
                          QRect clipRect;
                          if (!groovePixmapName.isEmpty())
                              groovePixmapName += "_blue"_L1;
                          if (!QPixmapCache::find(groovePixmapName, 
          &cache)) {
                              cache = styleCachePixmap(
          pixmapRect.size());
                              cache.fill(
          Qt::transparent);
                              QPainter groovePainter(&cache);
                              QLinearGradient gradient;
                              if (horizontal) {
                                  gradient.setStart(pixmapRect.center().x(), 
          pixmapRect.top());
                                  gradient.setFinalStop(pixmapRect.center().x(), 
          pixmapRect.bottom());
                              }
                              else {
                                  gradient.setStart(pixmapRect.left(), 
          pixmapRect.center().y());
                                  gradient.setFinalStop(pixmapRect.right(), 
          pixmapRect.center().y());
                              }
                              QColor highlight = d->highlight(
          option->palette);
                              QColor highlightedoutline = highlight.darker(
          140);
                              if (qGray(outline.rgb()) > qGray(
          highlightedoutline.rgb()))
                                  outline = highlightedoutline;
                              groovePainter.setRenderHint(QPainter::Antialiasing, 
          true);
                              groovePainter.translate(0.5, 
          0.5);
                              groovePainter.setPen(QPen(outline));
                              gradient.setColorAt(0, 
          activeHighlight);
                              gradient.setColorAt(1, activeHighlight.lighter(
          130));
                              groovePainter.setBrush(gradient);
                              groovePainter.drawRoundedRect(pixmapRect.adjusted(1, 1, -2, -2), 1, 
          1);
                              groovePainter.setPen(d->innerContrastLine());
                              groovePainter.setBrush(Qt::NoBrush);
                              groovePainter.drawRoundedRect(pixmapRect.adjusted(2, 2, -3, -3), 1, 
          1);
                              groovePainter.end();
                              QPixmapCache::insert(groovePixmapName, 
          cache);
                          }
                          if (horizontal) {
                              if (slider->upsideDown)
                                  clipRect = QRect(handle.right(), groove.top(), groove.right() - handle.right(), groove.height());
                              else
                                  clipRect = QRect(groove.left(), groove.top(), handle.left(), groove.height());
                          } else {
                              if (slider->upsideDown)
                                  clipRect = QRect(groove.left(), handle.bottom(), groove.width(), groove.height() - handle.bottom());
                              else
                                  clipRect = QRect(groove.left(), groove.top(), groove.width(), handle.top() - groove.top());
                          }
                          painter->save();
                          painter->setClipRect(clipRect.adjusted(0, 0, 1, 1), 
          Qt::IntersectClip);
                          painter->drawPixmap(groove.topLeft(), 
          cache);
                          painter->restore();
                      }
                      if (option->subControls & SC_SliderTickmarks) {
                          painter->setPen(outline);
                          int tickSize = proxy()->pixelMetric(
          PM_SliderTickmarkOffset, option, widget);
                          int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, 
          slider, widget);
                          int interval = slider->tickInterval;
                          if (interval <= 0) {
                              interval = slider->singleStep;
                              if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, 
          interval,
                                                                  
          available)
                                      - QStyle::sliderPositionFromValue(slider->minimum, 
          slider->maximum,
                                                                        0, 
          available) < 3)
                                  interval = slider->pageStep;
                          }
                          if (interval <= 0)
                              interval = 1;
                          int v = slider->minimum;
                          int len = proxy()->pixelMetric(PM_SliderLength, 
          slider, widget);
                          while (v <= slider->maximum + 1) {
                              if (v == slider->maximum + 1 && interval == 1)
                                  break;
                              const int v_ = qMin(v, 
          slider->maximum);
                              int pos = sliderPositionFromValue(slider->minimum, 
          slider->maximum,
                                                                v_, 
          (horizontal
                                                                     ? slider->rect.width()
                                                                     : slider->rect.height()) - len,
                                                                
          slider->upsideDown) + len / 2;
                              int extra = 2 - ((v_ == slider->minimum || v_ == slider->maximum) ? 1 : 0);
                              if (horizontal) {
                                  if (ticksAbove) {
                                      painter->drawLine(pos, 
          slider->rect.top() + extra,
                                                        pos, 
          slider->rect.top() + tickSize);
                                  }
                                  if (ticksBelow) {
                                      painter->drawLine(pos, 
          slider->rect.bottom() - extra,
                                                        pos, 
          slider->rect.bottom() - tickSize);
                                  }
                              } else {
                                  if (ticksAbove) {
                                      painter->drawLine(slider->rect.left() + extra, 
          pos,
                                                        slider->rect.left() + tickSize, 
          pos);
                                  }
                                  if (ticksBelow) {
                                      painter->drawLine(slider->rect.right() - extra, 
          pos,
                                                        slider->rect.right() - tickSize, 
          pos);
                                  }
                              }
                              // in the case where maximum is max int
                              int nextInterval = v + interval;
                              if (nextInterval < v)
                                  break;
                              v = nextInterval;
                          }
                      }
                      // draw handle
                      if ((option->subControls & SC_SliderHandle) ) {
                          QString handlePixmapName = QStyleHelper::uniqueName("slider_handle"_L1, option, 
          handle.size());
                          if (!QPixmapCache::find(handlePixmapName, 
          &cache)) {
                              cache = styleCachePixmap(
          handle.size());
                              cache.fill(
          Qt::transparent);
                              QRect pixmapRect(0, 0, handle.width(), handle.height());
                              QPainter handlePainter(&cache);
                              QRect gradRect = pixmapRect.adjusted(2, 2, -2, 
          -2);
                              // gradient fill
                              QRect r = pixmapRect.adjusted(1, 1, -2, 
          -2);
                              QLinearGradient gradient = qt_fusion_gradient(gradRect, d->buttonColor(option->palette),
          horizontal ? TopDown : FromLeft);
                              handlePainter.setRenderHint(QPainter::Antialiasing, 
          true);
                              handlePainter.translate(0.5, 
          0.5);
                              handlePainter.setPen(Qt::NoPen);
                              handlePainter.setBrush(QColor(0, 0, 0, 40));
                              handlePainter.drawRect(r.adjusted(-1, 2, 1, 
          -2));
                              handlePainter.setPen(QPen(d->outline(
          option->palette)));
                              if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
                                  handlePainter.setPen(QPen(d->highlightedOutline(
          option->palette)));
                              handlePainter.setBrush(gradient);
                              handlePainter.drawRoundedRect(r, 2, 
          2);
                              handlePainter.setBrush(Qt::NoBrush);
                              handlePainter.setPen(d->innerContrastLine());
                              handlePainter.drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 
          2);
                              QColor cornerAlpha = outline.darker(
          120);
                              cornerAlpha.setAlpha(80);
                              //handle shadow
                              handlePainter.setPen(shadowAlpha);
                              handlePainter.drawLine(QPoint(r.left() + 2, r.bottom() + 1), 
          QPoint(r.right() - 2, r.bottom() + 1));
                              handlePainter.drawLine(QPoint(r.right() + 1, r.bottom() - 3), 
          QPoint(r.right() + 1, r.top() + 4));
                              handlePainter.drawLine(QPoint(r.right() - 1, r.bottom()), 
          QPoint(r.right() + 1, r.bottom() - 2));
                              handlePainter.end();
                              QPixmapCache::insert(handlePixmapName, 
          cache);
                          }
                          painter->drawPixmap(handle.topLeft(), 
          cache);
                      }
                      painter->setBrush(oldBrush);
                      painter->setPen(oldPen);
                  }
                  break;
          #endif // QT_CONFIG(slider)
          
          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Hi,

            You can do it the same way the fusion style does but you have to tell qmake to use the widget-private module. Don't forget that using it will make your application highly dependent on the Qt version you use.

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • I ian28

              @JoeCFD Do stylesheets support custom states that are based on some values of my custom slider or do i have to update the stylesheet at runtime?

              JoeCFDJ Offline
              JoeCFDJ Offline
              JoeCFD
              wrote on last edited by
              #6

              @ian28 you can update or reset style sheet at running time.

              1 Reply Last reply
              0

              • Login

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • Users
              • Groups
              • Search
              • Get Qt Extensions
              • Unsolved