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
Forum Updated to NodeBB v4.3 + New Features

Coloring slider handle depending on state

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 3 Posters 461 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