原本是從這個(gè)庫https://github.com/ThisIsClark/Qt-RangeSlider 去下載的卓研,但是實(shí)際使用中發(fā)現(xiàn)豎直滑動(dòng)條的時(shí)候茵汰,他的大值的滑塊在下面役衡,小值的滑塊在上面曹体,嚴(yán)重反直覺混稽,遂自己修改了一下借杰,變量名也根據(jù)自己便于理解的方式稍作修改了罗心,工作在qt6下面:
頭文件
RangeSlider.h
#pragma once
#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
#include <QHBoxLayout>
class RangeSlider : public QWidget
{
Q_OBJECT
Q_ENUMS(RangeSliderTypes)
public:
enum Option
{
NoHandle = 0x0,
// LeftHandle = 0x1,
// RightHandle = 0x2,
// DoubleHandles = LeftHandle | RightHandle
MinHandle = 0x1,
MaxHandle = 0x2,
DoubleHandles = MinHandle | MaxHandle
};
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;
float GetMinimun() const;
void SetMinimum(float aMinimum);
float GetMaximun() const;
void SetMaximum(float aMaximum);
float GetLowerValue() const;
void SetLowerValue(float aLowerValue);
float GetUpperValue() const;
void SetUpperValue(float aUpperValue);
void SetRange(float aMinimum, float aMaximum);
protected:
void paintEvent(QPaintEvent *aEvent) override;
void mousePressEvent(QMouseEvent *aEvent) override;
void mouseMoveEvent(QMouseEvent *aEvent) override;
void mouseReleaseEvent(QMouseEvent *aEvent) override;
void changeEvent(QEvent *aEvent) override;
QRectF lowHandleRect() const;
QRectF moreHandleRect() const;
QRectF handleRect(float aValue) const;
signals:
void lowerValueChanged(float aLowerValue);
void upperValueChanged(float aUpperValue);
void rangeChanged(float aMin, float aMax);
void updownChanged(float aLowerValue, float aUpperValue);
public slots:
void setLowerValue(float aLowerValue);
void setUpperValue(float aUpperValue);
void setMinimum(float aMinimum);
void setMaximum(float aMaximum);
private:
Q_DISABLE_COPY(RangeSlider)
float currentPercentage();
float validLength() const;
float mMinimum;
float mMaximum;
float mLowerValue;
float mUpperValue;
bool mLowHandlePressed;
bool mMoreHandlePressed;
float mInterval;
float mDelta;
QColor mBackgroudColorEnabled;
QColor mBackgroudColorDisabled;
QColor mBackgroudColor;
Qt::Orientation orientation;
Options type;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(RangeSlider::Options)
源文件
RangeSlider
#include "RangeSlider.h"
#include <QDebug>
namespace
{
const float scHandleSideLength = 11;
const float scSliderBarHeight = 5;
const float scLeftRightMargin = 1;
}
RangeSlider::RangeSlider(QWidget *aParent)
: QWidget(aParent),
mMinimum(0),
mMaximum(100),
mLowerValue(0),
mUpperValue(100),
mLowHandlePressed(false),
mMoreHandlePressed(false),
mInterval(mMaximum - mMinimum),
mBackgroudColorEnabled(QColor(0x1E, 0x90, 0xFF)),
mBackgroudColorDisabled(Qt::darkGray),
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),
mLowHandlePressed(false),
mMoreHandlePressed(false),
mInterval(mMaximum - mMinimum),
mBackgroudColorEnabled(QColor(0x1E, 0x90, 0xFF)),
mBackgroudColorDisabled(Qt::darkGray),
mBackgroudColor(mBackgroudColorEnabled),
orientation(ori),
type(t)
{
setMouseTracking(true);
}
void RangeSlider::paintEvent(QPaintEvent *aEvent)
{
Q_UNUSED(aEvent);
QPainter painter(this);
// Background
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);
painter.setRenderHint(QPainter::Antialiasing);
QBrush backgroundBrush(QColor(0xD0, 0xD0, 0xD0));
painter.setBrush(backgroundBrush);
painter.drawRoundedRect(backgroundRect, 1, 1);
// First value handle rect
pen.setColor(Qt::darkGray);
pen.setWidth(0.5);
painter.setPen(pen);
painter.setRenderHint(QPainter::Antialiasing);
QBrush handleBrush(QColor(0xFA, 0xFA, 0xFA));
painter.setBrush(handleBrush);
QRectF MinHandleRect = lowHandleRect();
if (type.testFlag(MinHandle))
painter.drawRoundedRect(MinHandleRect, 2, 2);
// Second value handle rect
QRectF MaxHandleRect = moreHandleRect();
if (type.testFlag(MaxHandle))
painter.drawRoundedRect(MaxHandleRect, 2, 2);
// Handles
painter.setRenderHint(QPainter::Antialiasing, false);
QRectF selectedRect(backgroundRect); // 藍(lán)色選中區(qū)域
if (orientation == Qt::Horizontal)
{
selectedRect.setLeft((type.testFlag(MinHandle) ? MinHandleRect.right() : MinHandleRect.left()) + 0.5);
selectedRect.setRight((type.testFlag(MaxHandle) ? MaxHandleRect.left() : MaxHandleRect.right()) - 0.5);
}
else
{
selectedRect.setBottom((type.testFlag(MinHandle) ? MinHandleRect.top() : MinHandleRect.bottom()) - 0.5);
selectedRect.setTop((type.testFlag(MaxHandle) ? MaxHandleRect.bottom() : MaxHandleRect.top()) + 0.5);
}
QBrush selectedBrush(mBackgroudColor);
painter.setBrush(selectedBrush);
painter.drawRect(selectedRect);
}
/** ***************************************************************************
* @brief 繪制對(duì)應(yīng)小值的滑塊
* 水平的繪制在左邊吏砂,垂直的繪制在下面
*
* @return QRectF
* ************************************************************************** */
QRectF RangeSlider::lowHandleRect() const
{
float percentage{};
if (orientation == Qt::Horizontal)
{
percentage = (mLowerValue - mMinimum) * 1.0 / mInterval;
return handleRect(percentage * validLength() + scLeftRightMargin);
}
else
{
percentage = (mLowerValue - mMinimum) * 1.0 / mInterval;
percentage = 1 - percentage;
return handleRect(percentage * validLength() + scLeftRightMargin + (type.testFlag(MinHandle) ? scHandleSideLength : 0));
}
// return handleRect(percentage * validLength() + scLeftRightMargin);
}
/** ***************************************************************************
* @brief 繪制對(duì)應(yīng)大值的滑塊
* 水平繪制在右邊,垂直繪制在上面
*
* @return QRectF
* ************************************************************************** */
QRectF RangeSlider::moreHandleRect() const
{
float percentage{};
if (orientation == Qt::Horizontal)
{
percentage = (mUpperValue - mMinimum) * 1.0 / mInterval;
return handleRect(percentage * validLength() + scLeftRightMargin + (type.testFlag(MinHandle) ? scHandleSideLength : 0));
}
else
{
percentage = (mUpperValue - mMinimum) * 1.0 / mInterval;
percentage = 1 - percentage;
return handleRect(percentage * validLength() + scLeftRightMargin);
}
// return handleRect(percentage * validLength() + scLeftRightMargin + (type.testFlag(MinHandle) ? scHandleSideLength : 0));
}
/** ***************************************************************************
* @brief 繪制滑塊
*
* @param[in] aValue
* @return QRectF
* ************************************************************************** */
QRectF RangeSlider::handleRect(float aValue) const
{
if (orientation == Qt::Horizontal)
return QRect(aValue, (height() - scHandleSideLength) / 2, scHandleSideLength, scHandleSideLength);
else
return QRect((width() - scHandleSideLength) / 2, aValue, scHandleSideLength, scHandleSideLength);
}
/** ***************************************************************************
* @brief
*
* @param[in] aEvent
* ************************************************************************** */
void RangeSlider::mousePressEvent(QMouseEvent *aEvent)
{
if (aEvent->buttons() & Qt::LeftButton)
{
float posCheck, posMax, posValue, lowHandleRectPosValue, moreHandleRectPosValue;
if (orientation == Qt::Horizontal)
{
posCheck = aEvent->pos().y();
posMax = height();
posValue = aEvent->pos().x();
lowHandleRectPosValue = lowHandleRect().x();
moreHandleRectPosValue = moreHandleRect().x();
}
else
{
posCheck = aEvent->pos().x();
posMax = width();
posValue = height() - aEvent->pos().y();
lowHandleRectPosValue = height() - lowHandleRect().y();
moreHandleRectPosValue = height() - moreHandleRect().y();
}
mMoreHandlePressed = moreHandleRect().contains(aEvent->pos());
mLowHandlePressed = !mMoreHandlePressed && lowHandleRect().contains(aEvent->pos());
if (mLowHandlePressed)
{
mDelta = posValue - (lowHandleRectPosValue + scHandleSideLength / 2);
}
else if (mMoreHandlePressed)
{
mDelta = posValue - (moreHandleRectPosValue + scHandleSideLength / 2);
}
if (posCheck >= 2 && posCheck <= posMax - 2)
{
float step = mInterval / 50;
if (posValue < lowHandleRectPosValue)
setLowerValue(mLowerValue - step);
else if (((posValue > lowHandleRectPosValue + scHandleSideLength) || !type.testFlag(MinHandle)) && ((posValue < moreHandleRectPosValue) || !type.testFlag(MaxHandle)))
{
if (type.testFlag(DoubleHandles))
if (posValue - (lowHandleRectPosValue + scHandleSideLength) <
(moreHandleRectPosValue - (lowHandleRectPosValue + scHandleSideLength)) / 2)
setLowerValue((mLowerValue + step < mUpperValue) ? mLowerValue + step : mUpperValue);
else
setUpperValue((mUpperValue - step > mLowerValue) ? mUpperValue - step : mLowerValue);
else if (type.testFlag(MinHandle))
setLowerValue((mLowerValue + step < mUpperValue) ? mLowerValue + step : mUpperValue);
else if (type.testFlag(MaxHandle))
setUpperValue((mUpperValue - step > mLowerValue) ? mUpperValue - step : mLowerValue);
}
else if (posValue > moreHandleRectPosValue + scHandleSideLength)
setUpperValue(mUpperValue + step);
}
}
}
/** ***************************************************************************
* @brief
*
* @param[in] aEvent
* ************************************************************************** */
void RangeSlider::mouseMoveEvent(QMouseEvent *aEvent)
{
if (aEvent->buttons() & Qt::LeftButton)
{
float posValue, lowHandleRectPosValue, moreHandleRectPosValue;
if (orientation == Qt::Horizontal)
{
posValue = aEvent->pos().x();
lowHandleRectPosValue = lowHandleRect().x();
moreHandleRectPosValue = moreHandleRect().x();
}
else
{
posValue = height() - aEvent->pos().y();
lowHandleRectPosValue = height() - lowHandleRect().y();
moreHandleRectPosValue = height() - moreHandleRect().y();
}
if (mLowHandlePressed && type.testFlag(MinHandle))
{
if (posValue - mDelta + scHandleSideLength / 2 <= moreHandleRectPosValue)
{
setLowerValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2) * 1.0 / validLength() * mInterval + mMinimum);
}
else
{
setLowerValue(mUpperValue);
}
}
else if (mMoreHandlePressed && type.testFlag(MaxHandle))
{
if (lowHandleRectPosValue + scHandleSideLength * (type.testFlag(DoubleHandles) ? 1.5 : 0.5) <= posValue - mDelta)
{
setUpperValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2 - (type.testFlag(DoubleHandles) ? scHandleSideLength : 0)) * 1.0 / validLength() * mInterval + mMinimum);
}
else
{
setUpperValue(mLowerValue);
}
}
}
}
void RangeSlider::mouseReleaseEvent(QMouseEvent *aEvent)
{
Q_UNUSED(aEvent);
mLowHandlePressed = false;
mMoreHandlePressed = false;
}
void RangeSlider::changeEvent(QEvent *aEvent)
{
if (aEvent->type() == QEvent::EnabledChange)
{
if (isEnabled())
{
mBackgroudColor = mBackgroudColorEnabled;
}
else
{
mBackgroudColor = mBackgroudColorDisabled;
}
update();
}
}
QSize RangeSlider::minimumSizeHint() const
{
return QSize(scHandleSideLength * 2 + scLeftRightMargin * 2, scHandleSideLength);
}
float RangeSlider::GetMinimun() const
{
return mMinimum;
}
void RangeSlider::SetMinimum(float aMinimum)
{
setMinimum(aMinimum);
}
float RangeSlider::GetMaximun() const
{
return mMaximum;
}
void RangeSlider::SetMaximum(float aMaximum)
{
setMaximum(aMaximum);
}
float RangeSlider::GetLowerValue() const
{
return mLowerValue;
}
void RangeSlider::SetLowerValue(float aLowerValue)
{
setLowerValue(aLowerValue);
}
float RangeSlider::GetUpperValue() const
{
return mUpperValue;
}
void RangeSlider::SetUpperValue(float aUpperValue)
{
setUpperValue(aUpperValue);
}
void RangeSlider::setLowerValue(float aLowerValue)
{
if (aLowerValue > mMaximum)
{
aLowerValue = mMaximum;
}
if (aLowerValue < mMinimum)
{
aLowerValue = mMinimum;
}
mLowerValue = aLowerValue;
emit lowerValueChanged(mLowerValue);
emit updownChanged(mLowerValue, mUpperValue);
update();
}
void RangeSlider::setUpperValue(float aUpperValue)
{
if (aUpperValue > mMaximum)
{
aUpperValue = mMaximum;
}
if (aUpperValue < mMinimum)
{
aUpperValue = mMinimum;
}
mUpperValue = aUpperValue;
emit upperValueChanged(mUpperValue);
emit updownChanged(mLowerValue, mUpperValue);
update();
}
void RangeSlider::setMinimum(float aMinimum)
{
if (aMinimum <= mMaximum)
{
mMinimum = aMinimum;
}
else
{
float oldMax = mMaximum;
mMinimum = oldMax;
mMaximum = aMinimum;
}
mInterval = mMaximum - mMinimum;
update();
setLowerValue(mMinimum);
setUpperValue(mMaximum);
emit rangeChanged(mMinimum, mMaximum);
}
void RangeSlider::setMaximum(float aMaximum)
{
if (aMaximum >= mMinimum)
{
mMaximum = aMaximum;
}
else
{
float oldMin = mMinimum;
mMaximum = oldMin;
mMinimum = aMaximum;
}
mInterval = mMaximum - mMinimum;
update();
setLowerValue(mMinimum);
setUpperValue(mMaximum);
emit rangeChanged(mMinimum, mMaximum);
}
float RangeSlider::validLength() const
{
float len = (orientation == Qt::Horizontal) ? width() : height();
return len - scLeftRightMargin * 2 - scHandleSideLength * (type.testFlag(DoubleHandles) ? 2 : 1);
}
void RangeSlider::SetRange(float aMinimum, float mMaximum)
{
setMinimum(aMinimum);
setMaximum(mMaximum);
}