patterncppMinor
QSlider direct jump on click
Viewed 0 times
directclickqsliderjump
Problem
By default, QSlider move his thumbtrack by a value belonging to the singleStep() prop on mouse click. To make thumbtrack jump directly at the mouse click point, we need to create a new class inherited by QSlider.
Header file (.h):
Source file (.cpp):
```
#include "QImprovedSlider.h"
QImprovedSlider::QImprovedSlider(QWidget *parent) :
QSlider(parent)
{
}
QImprovedSlider::~QImprovedSlider()
{
}
void QImprovedSlider::mousePressEvent(QMouseEvent *event) {
QStyleOptionSlider opt;
initStyleOption(&opt);
QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
if (event->button() == Qt::LeftButton &&
!sr.contains(event->pos())) {
int newVal;
if (orientation() == Qt::Vertical) {
double halfHandleHeight = (0.5 * sr.height()) + 0.5;
int adaptedPosY = height() - event->y();
if ( adaptedPosY height() - halfHandleHeight )
adaptedPosY = height() - halfHandleHeight;
double newHeight = (height() - halfHandleHeight) - halfHandleHeight;
double normalizedPosition = (adaptedPosY - halfHandleHeight) / newHeight ;
newVal = minimum() + (maximum()-minimum()) * normalizedPosition;
} else {
double halfHandleWidth = (0.5 * sr.width()) + 0.5;
int adaptedPosX = event->x();
if ( adaptedPosX width() - halfHandleWidth )
adaptedPosX = width() - halfHandleWidth;
double newWidth = (width() - halfHandleWidth) - halfHandleWidth;
double normalizedPosition = (adaptedPosX - halfHandleWidth) / newWidt
Header file (.h):
#include
#include
#include
#include
#include
#include
#ifndef QIMPROVEDSLIDER_H
#define QIMPROVEDSLIDER_H
class QImprovedSlider : public QSlider
{
Q_OBJECT
protected:
void mousePressEvent(QMouseEvent *event);
public:
explicit QImprovedSlider(QWidget *parent = 0);
~QImprovedSlider();
public slots:
private:
private slots:
signals:
void onClick(int value);
};
#endif // QIMPROVEDSLIDER_HSource file (.cpp):
```
#include "QImprovedSlider.h"
QImprovedSlider::QImprovedSlider(QWidget *parent) :
QSlider(parent)
{
}
QImprovedSlider::~QImprovedSlider()
{
}
void QImprovedSlider::mousePressEvent(QMouseEvent *event) {
QStyleOptionSlider opt;
initStyleOption(&opt);
QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
if (event->button() == Qt::LeftButton &&
!sr.contains(event->pos())) {
int newVal;
if (orientation() == Qt::Vertical) {
double halfHandleHeight = (0.5 * sr.height()) + 0.5;
int adaptedPosY = height() - event->y();
if ( adaptedPosY height() - halfHandleHeight )
adaptedPosY = height() - halfHandleHeight;
double newHeight = (height() - halfHandleHeight) - halfHandleHeight;
double normalizedPosition = (adaptedPosY - halfHandleHeight) / newHeight ;
newVal = minimum() + (maximum()-minimum()) * normalizedPosition;
} else {
double halfHandleWidth = (0.5 * sr.width()) + 0.5;
int adaptedPosX = event->x();
if ( adaptedPosX width() - halfHandleWidth )
adaptedPosX = width() - halfHandleWidth;
double newWidth = (width() - halfHandleWidth) - halfHandleWidth;
double normalizedPosition = (adaptedPosX - halfHandleWidth) / newWidt
Solution
One issue I see, that has to do with functionality: since you are working with doubles, but your end values are integers, perhaps you should round the result.
The code above will set the handle one step before the end when you position the mouse at the end.
To fix, round the new position: replace
with
The code above will set the handle one step before the end when you position the mouse at the end.
To fix, round the new position: replace
newVal = minimum() + ((maximum()-minimum()) * normalizedPosition);with
newVal = minimum() + qRound((maximum()-minimum()) * normalizedPosition);Code Snippets
newVal = minimum() + ((maximum()-minimum()) * normalizedPosition);newVal = minimum() + qRound((maximum()-minimum()) * normalizedPosition);Context
StackExchange Code Review Q#140308, answer score: 2
Revisions (0)
No revisions yet.