QSlider handle and QProxyStyle
Unsolved
General and Desktop
-
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?
-
@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.