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. Reimplement QSlider paint-Event

Reimplement QSlider paint-Event

Scheduled Pinned Locked Moved General and Desktop
3 Posts 2 Posters 4.0k 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.
  • R Offline
    R Offline
    RuhigBrauner
    wrote on last edited by
    #1

    Hi,

    I would like to change the looks of the QSlider. Stylesheets won't help in this case so I decided to subclass QSlider and overwrite the paintEvent(QPaintEvent *event).

    However, I have some trouble with graphical bugs and also don't know how to approach this correctly.

    The first problem I have is that my handler can reach outside the bounding-Box of the Slider. This is actually problem of the code. I know I could fixe it by scaling / moving my graphicle elements a bit. However, I don't know how to fix this without messing up the hitbox for the mouse-interaction. Do you know how the QSlider itself deals with this problem?

    The second problem I have is a graphical glitch I see whenever I let go of the handler or draw the handler out of the slider bar. (I've linked two screenshots) It's a simple brigth line near the handler which isn't supposed to be there.

    My code is actually quite simple. Here are the important bits:

    @
    // calculate slider bar rectangle
    QRect sliderRect = event->rect();
    int width = sliderRect.width();
    int height = sliderRect.height();
    sliderRect.translate(0, (float)height*0.4);
    sliderRect.setHeight(sliderRect.height()*0.2);

    // draw the slider bar rectangle .....

    // calculate handler rectangle
    QRect handlerRect = event->rect();
    handlerRect.translate(0, (float)height*0.25);
    handlerRect.setWidth(handlerRect.height()*0.15);
    handlerRect.setHeight(handlerRect.height()*0.5);
    // calculate the position in pixel and offset half the handler width
    int handlerPos = ((float)(this->value()-this->minimum())/(float)this->maximum()) * event->rect().width() - handlerRect.width()*0.5;
    handlerRect.translate(handlerPos, 0);
    @

    Here are some screens with the graphical problem. The line is marked with the red box. What should be visible are the two rectangles with transparent fill.
    !https://studi.f4.htw-berlin.de/~s0539750/QSlider1.jpg(Example 1)!
    !https://studi.f4.htw-berlin.de/~s0539750/QSlider2.jpg(Example 2)!

    I hope you can help me. :)

    1 Reply Last reply
    0
    • T Offline
      T Offline
      taichi
      wrote on last edited by
      #2

      Hi,

      If you would like to change just the looks of slider widget, you can select the approach of changing widget's style. For example, you subclass the QProxyStyle and set it to widget.

      Here are two functions you might modify,

      @void MyStyle::drawComplexControl(ComplexControl control,
      const QStyleOptionComplex* option,
      QPainter* painter,
      const QWidget* widget) const
      {
      if (control == CC_Slider) {
      if (const QStyleOptionSlider* slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
      // paint groove
      painter->setPen(Qt::white);
      painter->setBrush(Qt::gray);
      painter->drawRect(subControlRect(CC_Slider, option, SC_SliderGroove, widget));
      // paint handle
      painter->setPen(QColor(255, 170, 0));
      painter->setBrush(QColor(255, 170, 0, 120));
      painter->drawRect(subControlRect(CC_Slider, option, SC_SliderHandle, widget));

              return;
          }
      }
      
      QProxyStyle::drawComplexControl(control, option, painter, widget);
      

      }

      QRect MyStyle::subControlRect(ComplexControl control,
      const QStyleOptionComplex *option,
      SubControl subControl,
      const QWidget *widget) const
      {
      QRect rect = QProxyStyle::subControlRect(control, option, subControl, widget);

      if (control == CC_Slider)
      {
          if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
              if (subControl == SC_SliderGroove) {
                  (slider->orientation == Qt::Horizontal) 
                      ? rect.setHeight(slider->rect.height() * 0.2)
                      : rect.setWidth(slider->rect.width() * 0.2);
                  rect.moveCenter(slider->rect.center());
              }
          }
      }
      return rect;
      

      }@

      and you can use this class like this,
      @MyStyle* style = new MyStyle(qApp->style());
      slider->setStyle(style);@

      1 Reply Last reply
      0
      • R Offline
        R Offline
        RuhigBrauner
        wrote on last edited by
        #3

        Hi,

        I fixed the function like this: Instead of using event->rect(), I used the bounding rectangle in the QSlider-class. It looks like the paint-function gets called for multiple parts of the slider which is in my opinion stupid. (The function shoudl be called once for an object and thets it)

        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