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

QSlider handle and QProxyStyle

Scheduled Pinned Locked Moved Unsolved General and Desktop
qsliderqproxystyle
2 Posts 2 Posters 1.1k 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.
  • 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

      2/2

      8 Jan 2017, 13:15

      • Login

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