Skip to content

Commit

Permalink
Merge pull request ThisIsClark#3 from nasafix-nasser/multi-type-slider
Browse files Browse the repository at this point in the history
Multi type slider
  • Loading branch information
ThisIsClark authored Jan 11, 2020
2 parents 575f557 + 59a3cb8 commit b3e381f
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 122 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*pro.user
*autosave
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Qt-RangeSlider
Implement range slider in Qt<br>
Here is the demo:<br>
![image](https://github.com/ThisIsClark/Qt-RangeSlider/blob/master/demo.gif)<br>
![image](https://github.com/nasafix-nasser/Qt-RangeSlider/blob/multi-type-slider/demo.gif)<br>
## How to use
1. Import RangeSlider.cpp & RangeSlider.h to your project.
2. Add a widget in Qt Designer.
3. Right click this widget to promote it to RangeSlider.
4. Now you can use this RangeSlider in your code.
4. Now you can use this RangeSlider in your code.
135 changes: 83 additions & 52 deletions RangeSlider.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include "RangeSlider.h"
#include <QDebug>

namespace
{
Expand All @@ -10,7 +11,6 @@ const int scLeftRightMargin = 1;

}


RangeSlider::RangeSlider(QWidget* aParent)
: QWidget(aParent),
mMinimum(0),
Expand All @@ -22,7 +22,26 @@ RangeSlider::RangeSlider(QWidget* aParent)
mInterval(mMaximum - mMinimum),
mBackgroudColorEnabled(QColor(0x1E, 0x90, 0xFF)),
mBackgroudColorDisabled(Qt::darkGray),
mBackgroudColor(mBackgroudColorEnabled)
mBackgroudColor(mBackgroudColorEnabled),
orientation(Qt::Horizontal)
{
setMouseTracking(true);
}

RangeSlider::RangeSlider(Qt::Orientation ori, Options t, QWidget* aParent)
: QWidget(aParent),
mMinimum(0),
mMaximum(100),
mLowerValue(0),
mUpperValue(100),
mFirstHandlePressed(false),
mSecondHandlePressed(false),
mInterval(mMaximum - mMinimum),
mBackgroudColorEnabled(QColor(0x1E, 0x90, 0xFF)),
mBackgroudColorDisabled(Qt::darkGray),
mBackgroudColor(mBackgroudColorEnabled),
orientation(ori),
type(t)
{
setMouseTracking(true);
}
Expand All @@ -33,7 +52,12 @@ void RangeSlider::paintEvent(QPaintEvent* aEvent)
QPainter painter(this);

// Background
QRectF backgroundRect = QRectF(scLeftRightMargin, (height() - scSliderBarHeight) / 2, width() - scLeftRightMargin * 2, scSliderBarHeight);
QRectF backgroundRect;
if(orientation == Qt::Horizontal)
backgroundRect = QRectF(scLeftRightMargin, (height() - scSliderBarHeight) / 2, width() - scLeftRightMargin * 2, scSliderBarHeight);
else
backgroundRect = QRectF((width() - scSliderBarHeight) / 2, scLeftRightMargin, scSliderBarHeight, height() - scLeftRightMargin*2);

QPen pen(Qt::gray, 0.8);
painter.setPen(pen);
painter.setRenderHint(QPainter::Qt4CompatiblePainting);
Expand All @@ -49,17 +73,24 @@ void RangeSlider::paintEvent(QPaintEvent* aEvent)
QBrush handleBrush(QColor(0xFA, 0xFA, 0xFA));
painter.setBrush(handleBrush);
QRectF leftHandleRect = firstHandleRect();
painter.drawRoundedRect(leftHandleRect, 2, 2);
if(type.testFlag(LeftHandle))
painter.drawRoundedRect(leftHandleRect, 2, 2);

// Second value handle rect
QRectF rightHandleRect = secondHandleRect();
painter.drawRoundedRect(rightHandleRect, 2, 2);
if(type.testFlag(RightHandle))
painter.drawRoundedRect(rightHandleRect, 2, 2);

// Handles
painter.setRenderHint(QPainter::Antialiasing, false);
QRectF selectedRect(backgroundRect);
selectedRect.setLeft(leftHandleRect.right() + 0.5);
selectedRect.setRight(rightHandleRect.left() - 0.5);
if(orientation == Qt::Horizontal) {
selectedRect.setLeft((type.testFlag(LeftHandle) ? leftHandleRect.right() : leftHandleRect.left()) + 0.5);
selectedRect.setRight((type.testFlag(RightHandle) ? rightHandleRect.left() : rightHandleRect.right()) - 0.5);
} else {
selectedRect.setTop((type.testFlag(LeftHandle) ? leftHandleRect.bottom() : leftHandleRect.top()) + 0.5);
selectedRect.setBottom((type.testFlag(RightHandle) ? rightHandleRect.top() : rightHandleRect.bottom()) - 0.5);
}
QBrush selectedBrush(mBackgroudColor);
painter.setBrush(selectedBrush);
painter.drawRect(selectedRect);
Expand All @@ -68,73 +99,67 @@ void RangeSlider::paintEvent(QPaintEvent* aEvent)
QRectF RangeSlider::firstHandleRect() const
{
float percentage = (mLowerValue - mMinimum) * 1.0 / mInterval;
return handleRect(percentage * validWidth() + scLeftRightMargin);
return handleRect(percentage * validLength() + scLeftRightMargin);
}

QRectF RangeSlider::secondHandleRect() const
{
float percentage = (mUpperValue - mMinimum) * 1.0 / mInterval;
return handleRect(percentage * validWidth() + scLeftRightMargin + scHandleSideLength);
return handleRect(percentage * validLength() + scLeftRightMargin + (type.testFlag(LeftHandle) ? scHandleSideLength : 0));
}

QRectF RangeSlider::handleRect(int aValue) const
{
return QRect(aValue, (height()-scHandleSideLength) / 2, scHandleSideLength, scHandleSideLength);
if(orientation == Qt::Horizontal)
return QRect(aValue, (height()-scHandleSideLength) / 2, scHandleSideLength, scHandleSideLength);
else
return QRect((width()-scHandleSideLength) / 2, aValue, scHandleSideLength, scHandleSideLength);
}

void RangeSlider::mousePressEvent(QMouseEvent* aEvent)
{
if(aEvent->buttons() & Qt::LeftButton)
{
int posCheck, posMax, posValue, firstHandleRectPosValue, secondHandleRectPosValue;
posCheck = (orientation == Qt::Horizontal) ? aEvent->pos().y() : aEvent->pos().x();
posMax = (orientation == Qt::Horizontal) ? height() : width();
posValue = (orientation == Qt::Horizontal) ? aEvent->pos().x() : aEvent->pos().y();
firstHandleRectPosValue = (orientation == Qt::Horizontal) ? firstHandleRect().x() : firstHandleRect().y();
secondHandleRectPosValue = (orientation == Qt::Horizontal) ? secondHandleRect().x() : secondHandleRect().y();

mSecondHandlePressed = secondHandleRect().contains(aEvent->pos());
mFirstHandlePressed = !mSecondHandlePressed && firstHandleRect().contains(aEvent->pos());
if(mFirstHandlePressed)
{
mDelta = aEvent->pos().x() - (firstHandleRect().x() + scHandleSideLength / 2);
mDelta = posValue - (firstHandleRectPosValue + scHandleSideLength / 2);
}
else if(mSecondHandlePressed)
{
mDelta = aEvent->pos().x() - (secondHandleRect().x() + scHandleSideLength / 2);
mDelta = posValue - (secondHandleRectPosValue + scHandleSideLength / 2);
}
if(aEvent->pos().y() >= 2
&& aEvent->pos().y() <= height()- 2)

if(posCheck >= 2
&& posCheck <= posMax - 2)
{
int step = mInterval / 10 < 1 ? 1 : mInterval / 10;
if(aEvent->pos().x() < firstHandleRect().x())
{
if(posValue < firstHandleRectPosValue)
setLowerValue(mLowerValue - step);
}
else if(aEvent->pos().x() > firstHandleRect().x() + scHandleSideLength
&& aEvent->pos().x() < secondHandleRect().x())
else if(((posValue > firstHandleRectPosValue + scHandleSideLength) || !type.testFlag(LeftHandle))
&& ((posValue < secondHandleRectPosValue) || !type.testFlag(RightHandle)))
{
if(aEvent->pos().x() - (firstHandleRect().x() + scHandleSideLength) <
(secondHandleRect().x() - (firstHandleRect().x() + scHandleSideLength)) / 2)
{
if(mLowerValue + step < mUpperValue)
{
setLowerValue(mLowerValue + step);
}
else
{
setLowerValue(mUpperValue);
}
}
else
{
if(mUpperValue - step > mLowerValue)
{
setUpperValue(mUpperValue - step);
}
if(type.testFlag(DoubleHandles))
if(posValue - (firstHandleRectPosValue + scHandleSideLength) <
(secondHandleRectPosValue - (firstHandleRectPosValue + scHandleSideLength)) / 2)
setLowerValue((mLowerValue + step < mUpperValue) ? mLowerValue + step : mUpperValue);
else
{
setUpperValue(mLowerValue);
}
}
setUpperValue((mUpperValue - step > mLowerValue) ? mUpperValue - step : mLowerValue);
else if(type.testFlag(LeftHandle))
setLowerValue((mLowerValue + step < mUpperValue) ? mLowerValue + step : mUpperValue);
else if(type.testFlag(RightHandle))
setUpperValue((mUpperValue - step > mLowerValue) ? mUpperValue - step : mLowerValue);
}
else if(aEvent->pos().x() > secondHandleRect().x() + scHandleSideLength)
{
else if(posValue > secondHandleRectPosValue + scHandleSideLength)
setUpperValue(mUpperValue + step);
}
}
}
}
Expand All @@ -143,22 +168,27 @@ void RangeSlider::mouseMoveEvent(QMouseEvent* aEvent)
{
if(aEvent->buttons() & Qt::LeftButton)
{
if(mFirstHandlePressed)
int posValue, firstHandleRectPosValue, secondHandleRectPosValue;
posValue = (orientation == Qt::Horizontal) ? aEvent->pos().x() : aEvent->pos().y();
firstHandleRectPosValue = (orientation == Qt::Horizontal) ? firstHandleRect().x() : firstHandleRect().y();
secondHandleRectPosValue = (orientation == Qt::Horizontal) ? secondHandleRect().x() : secondHandleRect().y();

if(mFirstHandlePressed && type.testFlag(LeftHandle))
{
if(aEvent->pos().x() - mDelta + scHandleSideLength / 2 <= secondHandleRect().x())
if(posValue - mDelta + scHandleSideLength / 2 <= secondHandleRectPosValue)
{
setLowerValue((aEvent->pos().x() - mDelta - scLeftRightMargin - scHandleSideLength / 2) * 1.0 / validWidth() * mInterval + mMinimum);
setLowerValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2) * 1.0 / validLength() * mInterval + mMinimum);
}
else
{
setLowerValue(mUpperValue);
}
}
else if(mSecondHandlePressed)
else if(mSecondHandlePressed && type.testFlag(RightHandle))
{
if(firstHandleRect().x() + scHandleSideLength * 1.5 <= aEvent->pos().x() - mDelta)
if(firstHandleRectPosValue + scHandleSideLength * (type.testFlag(DoubleHandles) ? 1.5 : 0.5) <= posValue - mDelta)
{
setUpperValue((aEvent->pos().x() - mDelta - scLeftRightMargin - scHandleSideLength / 2 - scHandleSideLength) * 1.0 / validWidth() * mInterval + mMinimum);
setUpperValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2 - (type.testFlag(DoubleHandles) ? scHandleSideLength : 0)) * 1.0 / validLength() * mInterval + mMinimum);
}
else
{
Expand Down Expand Up @@ -315,9 +345,10 @@ void RangeSlider::setMaximum(int aMaximum)
emit rangeChanged(mMinimum, mMaximum);
}

int RangeSlider::validWidth() const
int RangeSlider::validLength() const
{
return width() - scLeftRightMargin * 2 - scHandleSideLength * 2;
int len = (orientation == Qt::Horizontal) ? width() : height();
return len - scLeftRightMargin * 2 - scHandleSideLength * (type.testFlag(DoubleHandles) ? 2 : 1);
}

void RangeSlider::SetRange(int aMinimum, int mMaximum)
Expand Down
18 changes: 16 additions & 2 deletions RangeSlider.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,19 @@
class RangeSlider : public QWidget
{
Q_OBJECT
Q_ENUMS(RangeSliderTypes)

public:
RangeSlider(QWidget* aParent = Q_NULLPTR);
enum Option {
NoHandle = 0x0,
LeftHandle = 0x1,
RightHandle = 0x2,
DoubleHandles = LeftHandle | RightHandle
};
Q_DECLARE_FLAGS(Options, Option)

RangeSlider( QWidget* aParent = Q_NULLPTR);
RangeSlider( Qt::Orientation ori, Options t = DoubleHandles, QWidget* aParent = Q_NULLPTR);

QSize minimumSizeHint() const override;

Expand Down Expand Up @@ -52,7 +62,7 @@ public slots:
private:
Q_DISABLE_COPY(RangeSlider)
float currentPercentage();
int validWidth() const;
int validLength() const;

int mMinimum;
int mMaximum;
Expand All @@ -65,4 +75,8 @@ public slots:
QColor mBackgroudColorEnabled;
QColor mBackgroudColorDisabled;
QColor mBackgroudColor;
Qt::Orientation orientation;
Options type;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(RangeSlider::Options)
3 changes: 2 additions & 1 deletion RangeSlider.pro
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ DEFINES += QT_DEPRECATED_WARNINGS
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

QMAKE_CXXFLAGS += -std=gnu++11

SOURCES += main.cpp\
mainwindow.cpp \
Expand All @@ -30,4 +31,4 @@ SOURCES += main.cpp\
HEADERS += mainwindow.h \
RangeSlider.h

FORMS += mainwindow.ui
FORMS +=
Binary file modified demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 21 additions & 5 deletions mainwindow.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
#include <QDesktopWidget>
#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
QMainWindow(parent)
{
ui->setupUi(this);
widget = new QWidget(this);
rsH = new RangeSlider(Qt::Horizontal, RangeSlider::Option::DoubleHandles, nullptr);
rsV = new RangeSlider(Qt::Vertical, RangeSlider::Option::DoubleHandles, nullptr);
rsHsingleLeft = new RangeSlider(Qt::Horizontal, RangeSlider::Option::LeftHandle, nullptr);
rsVsingleLeft = new RangeSlider(Qt::Vertical, RangeSlider::Option::LeftHandle, nullptr);
rsHsingleRight = new RangeSlider(Qt::Horizontal, RangeSlider::Option::RightHandle, nullptr);
rsVsingleRight = new RangeSlider(Qt::Vertical, RangeSlider::Option::RightHandle, nullptr);

layout = new QHBoxLayout();
layout->addWidget(rsH);
layout->addWidget(rsV);
layout->addWidget(rsHsingleLeft);
layout->addWidget(rsVsingleLeft);
layout->addWidget(rsHsingleRight);
layout->addWidget(rsVsingleRight);

widget->setLayout(layout);
setCentralWidget(widget);
resize(QDesktopWidget().availableGeometry(this).size() * 0.7);
}

MainWindow::~MainWindow()
{
delete ui;
}
7 changes: 6 additions & 1 deletion mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#define MAINWINDOW_H

#include <QMainWindow>
#include <QHBoxLayout>
#include "RangeSlider.h"

namespace Ui {
class MainWindow;
Expand All @@ -12,11 +14,14 @@ class MainWindow : public QMainWindow
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();

private:
Ui::MainWindow *ui;
QWidget *widget;
RangeSlider *rsH, *rsV, *rsHsingleLeft, *rsVsingleLeft, *rsHsingleRight, *rsVsingleRight;
QHBoxLayout *layout;
};

#endif // MAINWINDOW_H
Loading

0 comments on commit b3e381f

Please sign in to comment.