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. QSlider handle and QProxyStyle
Forum Update on Monday, May 27th 2025

QSlider handle and QProxyStyle

Scheduled Pinned Locked Moved Unsolved General and Desktop
qsliderqproxystyle
2 Posts 2 Posters 1.1k Views
  • 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.
  • U Offline
    U Offline
    UnitScan
    wrote on 7 Jan 2017, 20:27 last edited by
    #1

    By default, QSlider move his thumbtrack by a value belonging to the pageStep() prop on mouse click. To make thumbtrack jump directly at the mouse click point, we need to create a new class inherited by QSlider.

    .h

    #ifndef QIMPROVEDSLIDER_H
    #define QIMPROVEDSLIDER_H
    
    #include <QSlider>
    
    class QImprovedSlider : public QSlider
    {
        Q_OBJECT
    protected:
        void mousePressEvent(QMouseEvent *event) override;
        void mouseReleaseEvent(QMouseEvent *event) override;
    public:
        explicit QImprovedSlider(QWidget *parent = 0);
    
    signals:
        void clicked(int value) const;
    
    };
    
    #endif // QIMPROVEDSLIDER_H
    

    .cpp

        #include <QWidget>
        #include <QMouseEvent>
        #include <QStyle>
        #include <QStyleOptionSlider>
        #include <QProxyStyle>
        #include "QImprovedSlider.h"
    
        class QImprovedSliderStyle : public QProxyStyle
        {
        public:
            using QProxyStyle::QProxyStyle;
            int styleHint(QStyle::StyleHint hint, const QStyleOption* option = 0,
                          const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const
            {
                if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
                    return (Qt::LeftButton | Qt::MidButton | Qt::RightButton);
                return QProxyStyle::styleHint(hint, option, widget, returnData);
            }
        };
    
        QImprovedSlider::QImprovedSlider(QWidget *parent) :
            QSlider(parent)
        {
            setStyle(new QImprovedSliderStyle(this->style()));
        }
    
    
        void QImprovedSlider::mousePressEvent(QMouseEvent *event) {
        QStyleOptionSlider opt;
        initStyleOption(&opt);
        QRect sr = style()->subControlRect(QStyle::CC_Slider,
                                           &opt,
                                           QStyle::SC_SliderHandle,
                                           this);
        qDebug() << sr.height() << sr.width();
        if (!sr.contains(event->pos()) && event->button() == Qt::LeftButton) {
            if (orientation() == Qt::Vertical)
                setValue(minimum() + ((maximum()-minimum()) * (height()-event->y())) / height() ) ;
            else
                setValue(minimum() + ((maximum()-minimum()) * event->x()) / width() ) ;
        }
        QSlider::mousePressEvent(event);
    }
    
    
        void QImprovedSlider::mouseReleaseEvent(QMouseEvent *event) {
            if (event->button() == Qt::LeftButton) {
                emit clicked(value());
                QSlider::mouseReleaseEvent(event);
            }
        }
    

    QImprovedSliderStyle make the handle drag more fluid, but in this way, the event is fired even when the click falls inside the handle, while the condition

    !sr.contains(event->pos())
    

    should avoid this.

    Can you help me?

    R 1 Reply Last reply 8 Jan 2017, 13:15
    0
    • U UnitScan
      7 Jan 2017, 20:27

      By default, QSlider move his thumbtrack by a value belonging to the pageStep() prop on mouse click. To make thumbtrack jump directly at the mouse click point, we need to create a new class inherited by QSlider.

      .h

      #ifndef QIMPROVEDSLIDER_H
      #define QIMPROVEDSLIDER_H
      
      #include <QSlider>
      
      class QImprovedSlider : public QSlider
      {
          Q_OBJECT
      protected:
          void mousePressEvent(QMouseEvent *event) override;
          void mouseReleaseEvent(QMouseEvent *event) override;
      public:
          explicit QImprovedSlider(QWidget *parent = 0);
      
      signals:
          void clicked(int value) const;
      
      };
      
      #endif // QIMPROVEDSLIDER_H
      

      .cpp

          #include <QWidget>
          #include <QMouseEvent>
          #include <QStyle>
          #include <QStyleOptionSlider>
          #include <QProxyStyle>
          #include "QImprovedSlider.h"
      
          class QImprovedSliderStyle : public QProxyStyle
          {
          public:
              using QProxyStyle::QProxyStyle;
              int styleHint(QStyle::StyleHint hint, const QStyleOption* option = 0,
                            const QWidget* widget = 0, QStyleHintReturn* returnData = 0) const
              {
                  if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
                      return (Qt::LeftButton | Qt::MidButton | Qt::RightButton);
                  return QProxyStyle::styleHint(hint, option, widget, returnData);
              }
          };
      
          QImprovedSlider::QImprovedSlider(QWidget *parent) :
              QSlider(parent)
          {
              setStyle(new QImprovedSliderStyle(this->style()));
          }
      
      
          void QImprovedSlider::mousePressEvent(QMouseEvent *event) {
          QStyleOptionSlider opt;
          initStyleOption(&opt);
          QRect sr = style()->subControlRect(QStyle::CC_Slider,
                                             &opt,
                                             QStyle::SC_SliderHandle,
                                             this);
          qDebug() << sr.height() << sr.width();
          if (!sr.contains(event->pos()) && event->button() == Qt::LeftButton) {
              if (orientation() == Qt::Vertical)
                  setValue(minimum() + ((maximum()-minimum()) * (height()-event->y())) / height() ) ;
              else
                  setValue(minimum() + ((maximum()-minimum()) * event->x()) / width() ) ;
          }
          QSlider::mousePressEvent(event);
      }
      
      
          void QImprovedSlider::mouseReleaseEvent(QMouseEvent *event) {
              if (event->button() == Qt::LeftButton) {
                  emit clicked(value());
                  QSlider::mouseReleaseEvent(event);
              }
          }
      

      QImprovedSliderStyle make the handle drag more fluid, but in this way, the event is fired even when the click falls inside the handle, while the condition

      !sr.contains(event->pos())
      

      should avoid this.

      Can you help me?

      R Offline
      R Offline
      raven-worx
      Moderators
      wrote on 8 Jan 2017, 13:15 last edited by
      #2

      @UnitScan
      alternatively you could "hack" a little bit.
      set the step size to 1 and max value to the widgets width. Update the max value on every resize (and also recalculate the value).
      You then create custom setter for your"real" max value and a new signal with the "real" value calculated linear to the base max value.

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      1

      1/2

      7 Jan 2017, 20:27

      • Login

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