目录
说明:这里参考许多大佬资料,但是当时记着赶项目,忘记搜集大佬们链接,非常感谢大佬们无私奉献。
2.继承QSlider(有缺陷,部分功能没有实现,可以研究一下)
说明:这里参考许多大佬资料,但是当时记着赶项目,忘记搜集大佬们链接,非常感谢大佬们无私奉献。
1.继承QWidget
如果项目需求对QSlider要求不高(使用自绘方法,无法使用样式)继承QWidget,里面基本功能都实现了,个别需要自己在研究实现,效果如如下
#pragma once
#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
class RangeSlider : public QWidget
{
Q_OBJECT
Q_ENUMS(RangeSliderTypes)
public:
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;
int GetMinimun() const;
void SetMinimum(int aMinimum);
int GetMaximun() const;
void SetMaximum(int aMaximum);
int GetLowerValue() const;
void SetLowerValue(int aLowerValue);
int GetUpperValue() const;
void SetUpperValue(int aUpperValue);
void SetRange(int aMinimum, int 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 firstHandleRect() const;
QRectF secondHandleRect() const;
QRectF handleRect(int aValue) const;
signals:
void lowerValueChanged(int aLowerValue);
void upperValueChanged(int aUpperValue);
void rangeChanged(int aMin, int aMax);
public slots:
void setLowerValue(int aLowerValue);
void setUpperValue(int aUpperValue);
void setMinimum(int aMinimum);
void setMaximum(int aMaximum);
private:
Q_DISABLE_COPY(RangeSlider)
float currentPercentage();
int validLength() const;
int mMinimum;
int mMaximum;
int mLowerValue;
int mUpperValue;
bool mFirstHandlePressed;
bool mSecondHandlePressed;
int mInterval;
int mDelta;
QColor mBackgroudColorEnabled;
QColor mBackgroudColorDisabled;
QColor mBackgroudColor;
Qt::Orientation orientation;
Options type;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(RangeSlider::Options)
#include "RangeSlider.h"
#include <QDebug>
namespace
{
const int scHandleSideLength = 11;
const int scSliderBarHeight = 5;
const int scLeftRightMargin = 1;
}
RangeSlider::RangeSlider(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(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);
}
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);
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 leftHandleRect = firstHandleRect();
if(type.testFlag(LeftHandle))
painter.drawRoundedRect(leftHandleRect, 2, 2);
// Second value handle rect
QRectF rightHandleRect = secondHandleRect();
if(type.testFlag(RightHandle))
painter.drawRoundedRect(rightHandleRect, 2, 2);
// Handles
painter.setRenderHint(QPainter::Antialiasing, false);
QRectF selectedRect(backgroundRect);
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);
}
QRectF RangeSlider::firstHandleRect() const
{
float percentage = (mLowerValue - mMinimum) * 1.0 / mInterval;
return handleRect(percentage * validLength() + scLeftRightMargin);
}
QRectF RangeSlider::secondHandleRect() const
{
float percentage = (mUpperValue - mMinimum) * 1.0 / mInterval;
return handleRect(percentage * validLength() + scLeftRightMargin + (type.testFlag(LeftHandle) ? scHandleSideLength : 0));
}
QRectF RangeSlider::handleRect(int aValue) const
{
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 = posValue - (firstHandleRectPosValue + scHandleSideLength / 2);
}
else if(mSecondHandlePressed)
{
mDelta = posValue - (secondHandleRectPosValue + scHandleSideLength / 2);
}
if(posCheck >= 2
&& posCheck <= posMax - 2)
{
int step = mInterval / 10 < 1 ? 1 : mInterval / 10;
if(posValue < firstHandleRectPosValue)
setLowerValue(mLowerValue - step);
else if(((posValue > firstHandleRectPosValue + scHandleSideLength) || !type.testFlag(LeftHandle))
&& ((posValue < secondHandleRectPosValue) || !type.testFlag(RightHandle)))
{
if(type.testFlag(DoubleHandles))
if(posValue - (firstHandleRectPosValue + scHandleSideLength) <
(secondHandleRectPosValue - (firstHandleRectPosValue + scHandleSideLength)) / 2)
setLowerValue((mLowerValue + step < mUpperValue) ? mLowerValue + step : mUpperValue);
else
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(posValue > secondHandleRectPosValue + scHandleSideLength)
setUpperValue(mUpperValue + step);
}
}
}
void RangeSlider::mouseMoveEvent(QMouseEvent* aEvent)
{
if(aEvent->buttons() & Qt::LeftButton)
{
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(posValue - mDelta + scHandleSideLength / 2 <= secondHandleRectPosValue)
{
setLowerValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2) * 1.0 / validLength() * mInterval + mMinimum);
}
else
{
setLowerValue(mUpperValue);
}
}
else if(mSecondHandlePressed && type.testFlag(RightHandle))
{
if(firstHandleRectPosValue + 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);
mFirstHandlePressed = false;
mSecondHandlePressed = 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);
}
int RangeSlider::GetMinimun() const
{
return mMinimum;
}
void RangeSlider::SetMinimum(int aMinimum)
{
setMinimum(aMinimum);
}
int RangeSlider::GetMaximun() const
{
return mMaximum;
}
void RangeSlider::SetMaximum(int aMaximum)
{
setMaximum(aMaximum);
}
int RangeSlider::GetLowerValue() const
{
return mLowerValue;
}
void RangeSlider::SetLowerValue(int aLowerValue)
{
setLowerValue(aLowerValue);
}
int RangeSlider::GetUpperValue() const
{
return mUpperValue;
}
void RangeSlider::SetUpperValue(int aUpperValue)
{
setUpperValue(aUpperValue);
}
void RangeSlider::setLowerValue(int aLowerValue)
{
if(aLowerValue > mMaximum)
{
aLowerValue = mMaximum;
}
if(aLowerValue < mMinimum)
{
aLowerValue = mMinimum;
}
mLowerValue = aLowerValue;
emit lowerValueChanged(mLowerValue);
update();
}
void RangeSlider::setUpperValue(int aUpperValue)
{
if(aUpperValue > mMaximum)
{
aUpperValue = mMaximum;
}
if(aUpperValue < mMinimum)
{
aUpperValue = mMinimum;
}
mUpperValue = aUpperValue;
emit upperValueChanged(mUpperValue);
update();
}
void RangeSlider::setMinimum(int aMinimum)
{
if(aMinimum <= mMaximum)
{
mMinimum = aMinimum;
}
else
{
int oldMax = mMaximum;
mMinimum = oldMax;
mMaximum = aMinimum;
}
mInterval = mMaximum - mMinimum;
update();
setLowerValue(mMinimum);
setUpperValue(mMaximum);
emit rangeChanged(mMinimum, mMaximum);
}
void RangeSlider::setMaximum(int aMaximum)
{
if(aMaximum >= mMinimum)
{
mMaximum = aMaximum;
}
else
{
int oldMin = mMinimum;
mMaximum = oldMin;
mMinimum = aMaximum;
}
mInterval = mMaximum - mMinimum;
update();
setLowerValue(mMinimum);
setUpperValue(mMaximum);
emit rangeChanged(mMinimum, mMaximum);
}
int RangeSlider::validLength() const
{
int len = (orientation == Qt::Horizontal) ? width() : height();
return len - scLeftRightMargin * 2 - scHandleSideLength * (type.testFlag(DoubleHandles) ? 2 : 1);
}
void RangeSlider::SetRange(int aMinimum, int mMaximum)
{
setMinimum(aMinimum);
setMaximum(mMaximum);
}
//调用方法 这里只写代码段 .h
QHBoxLayout *layout;
RangeSlider *rsH, *rsV, *rsHsingleLeft, *rsVsingleLeft, *rsHsingleRight, *rsVsingleRight;
//.cpp
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);
2.继承QSlider(有缺陷,部分功能没有实现,可以研究一下)
该方法使用QPixmap贴图方式,然后将贴图在滑条范围内移动,下面分别是.h和cpp
#ifndef SUPERSLIDER_H
#define SUPERSLIDER_H
#pragma once
#include "qslider.h"
#include "qlabel.h"
/*
* Super sick nasty awesome double handled slider!
*
* @author Steve
*/
class SuperSliderHandle;
class SuperSlider: public QSlider
{
Q_OBJECT
public:
SuperSlider(QWidget *parent = 0);
SuperSliderHandle *alt_handle;
void mouseReleaseEvent(QMouseEvent *event);
int alt_value();
void alt_setValue(int value);
void Reset();
void alt_update();
signals:
void alt_valueChanged(int);
};
class SuperEventFilter : public QObject
{
public:
SuperEventFilter(SuperSlider *_grandParent)
{grandParent = _grandParent;};
protected:
bool eventFilter(QObject* obj, QEvent* event);
private:
SuperSlider *grandParent;
};
class SuperSliderHandle: public QLabel
{
Q_OBJECT
public:
SuperSliderHandle(SuperSlider *parent = 0);
void mousePressEvent(QMouseEvent *event);
int value();
int mapValue();
SuperSlider *parent;
bool handleActivated;
private:
SuperEventFilter *filter;
public slots:
void setValue(double value);
};
#endif // SUPERSLIDER_H
#include "SuperSlider.h"
//Qt
#include <QMouseEvent>
#include "qmimedata.h"
#include "qdrag.h"
#include "qwidgetaction.h"
#include "qapplication.h"
#include "qpixmap.h"
#include "qcursor.h"
#include "qguiapplication.h"
#include "qdir.h"
#include <QProxyStyle>
class SliderProxy : public QProxyStyle
{
public:
int pixelMetric ( PixelMetric metric, const QStyleOption * option = 0, const QWidget * widget = 0 ) const
{
switch(metric) {
case PM_SliderThickness : return 25;
case PM_SliderLength : return 25;
default : return (QProxyStyle::pixelMetric(metric,option,widget));
}
}
};
SuperSlider::SuperSlider(QWidget *parent)
: QSlider(parent)
{
//styling
setOrientation(Qt::Horizontal);
setAcceptDrops(true);
SliderProxy *aSliderProxy = new SliderProxy();
//hard coded path to image :/ sorry
QString path = "d:/1.png";// QDir::fromNativeSeparators(ImagesPath("handle.png"));
setStyleSheet("QSlider::handle { image: url(" + path + "); }");
setStyle(aSliderProxy);
//setting up the alternate handle
alt_handle = new SuperSliderHandle(this);
addAction(new QWidgetAction(alt_handle));
alt_handle->move(this->pos().x() + this->width()- alt_handle->width(), this->pos().y() );
}
SuperSliderHandle::SuperSliderHandle(SuperSlider *_parent)
: QLabel(_parent)
{
parent = _parent;
filter = new SuperEventFilter(parent);
//styling
setAcceptDrops(true);
//hard coded path to image :/ sorry
QPixmap pix = QPixmap("d:/2.png");//QPixmap(ImagesPath("handle.png"));
pix = pix.scaled(25, 25, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
setPixmap(pix);
}
int SuperSlider::alt_value()
{
return alt_handle->value();
}
void SuperSlider::alt_setValue(int value)
{
alt_handle->setValue(value);
}
void SuperSlider::mouseReleaseEvent(QMouseEvent *mouseEvent)
{
if (mouseEvent->button() == Qt::LeftButton)
{
alt_handle->show();
alt_handle->handleActivated = false;
}
mouseEvent->accept();
}
void SuperSlider::alt_update()
{
QPoint posCursor(QCursor::pos());
QPoint posParent(mapToParent(mapToGlobal(pos())));
QPoint point(alt_handle->mapToParent(alt_handle->mapFromGlobal(QCursor::pos())).x(),alt_handle->y());
int horBuffer = (alt_handle->width());
bool lessThanMax = mapToParent(point).x() < pos().x()+ width() - horBuffer;
bool greaterThanMin = mapToParent(point).x() > pos().x();
if(lessThanMax && greaterThanMin)
alt_handle->move(point);
emit alt_valueChanged(alt_value());
}
void SuperSliderHandle::mousePressEvent(QMouseEvent *mouseEvent)
{
qGuiApp->installEventFilter(filter);
parent->clearFocus();
}
bool SuperEventFilter::eventFilter(QObject* obj, QEvent* event)
{
switch(event->type())
{
case QEvent::MouseButtonRelease:
qGuiApp->removeEventFilter(this);
return true;
break;
case QEvent::MouseMove:
grandParent->alt_update();
return true;
break;
default:
return QObject::eventFilter(obj, event);
}
return false;
}
void SuperSliderHandle::setValue(double value)
{
double width = parent->width(), position = pos().x();
double range = parent->maximum() - parent->minimum();
int location = (value - parent->minimum())/range;
location = location *width;
move(y(),location);
}
int SuperSliderHandle::value()
{
double width = parent->width(), position = pos().x();
double value = position/width;
double range = parent->maximum() - parent->minimum();
return parent->minimum() + (value * range);
}
void SuperSlider::Reset()
{
int horBuffer = (alt_handle->width());
QPoint myPos = mapToGlobal(pos());
QPoint point(myPos.x() + width() - horBuffer, myPos.y()- alt_handle->height());
point = alt_handle->mapFromParent(point);
alt_handle->move(point);
alt_handle->show();
alt_handle->raise();
}
3.继承QWidget与1有点异曲同工之处(也是自绘)
#pragma once
#include <QWidget>
#include <QWidget>
#include <QPainter>
#include <QMouseEvent>
#include <QFontMetrics>
#include "ui_CNW24GDoubleSlider.h"
class DoubleSlider;
class CNW24GDoubleSlider : public QWidget
{
Q_OBJECT
public:
CNW24GDoubleSlider(QWidget *parent = nullptr);
~CNW24GDoubleSlider();
private:
DoubleSlider* m_pDoubleSlider = nullptr;
private:
Ui::CNW24GDoubleSliderClass ui;
};
class DoubleSlider : public QWidget
{
Q_OBJECT
public:
DoubleSlider(QWidget* parent = 0);
void setRange(float min, float max);
void setSingleStep(float step);
enum State { MinHandle, MaxHandle, None };
float minValue() const;
float maxValue() const;
float minRange() const;
float maxRange() const;
void SetPressValue(float fpos);
void SetValue(int npos);
public slots:
void setLabel(const QString& label);
void setMaxValue(float val);
void setMinValue(float val);
signals:
void minValueChanged(float);
void maxValueChanged(float);
private:
float m_min;
float m_max;
float m_singleStep;
float m_minValue;
float m_maxValue;
QRect minHandleRegion;
QRect maxHandleRegion;
State m_state;
QString m_label;
protected:
void paintEvent(QPaintEvent* event);
void paintColoredRect(QRect rect, QColor color, QPainter* painter);
void paintValueLabel(QPainter* painter);
void mousePressEvent(QMouseEvent* event);
void mouseMoveEvent(QMouseEvent* event);
void keyPressEvent(QKeyEvent* event);
void leaveEvent(QEvent* event);
};
#include "CNW24GDoubleSlider.h"
CNW24GDoubleSlider::CNW24GDoubleSlider(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
ui.nameLabel->setText(u8"亮度");
ui.nameLabel->setStyleSheet("width: 54px;height: 20px;color: #FFFFFF; background-color:none;");
m_pDoubleSlider = new DoubleSlider(this);
m_pDoubleSlider->move(30, 50);
}
CNW24GDoubleSlider::~CNW24GDoubleSlider()
{
}
/// <summary>
/// DoubleSlider
/// </summary>
/// <param name="parent"></param>
DoubleSlider::DoubleSlider(QWidget* parent)
: QWidget(parent)
, m_min(0.0f)
, m_max(100.0f)
, m_singleStep(0.1f)
, m_minValue(0.0f)
, m_maxValue(100.0f)
, m_state(None)
{
setFixedWidth(200);
setFixedHeight(550);
setFocusPolicy(Qt::StrongFocus);
}
void DoubleSlider::paintEvent(QPaintEvent* event)
{
QWidget::paintEvent(event);
QPainter painter(this);
paintValueLabel(&painter);
}
void DoubleSlider::paintColoredRect(QRect rect, QColor color, QPainter* painter)
{
painter->fillRect(rect, QBrush(color));
}
void DoubleSlider::paintValueLabel(QPainter* painter)
{
// painter->setBrush(Qt::NoBrush);
painter->setBrush(Qt::NoBrush);
painter->setPen(Qt::white);
painter->setFont(QFont("Arial", 12));
QString minValueString = QString::number(m_minValue, 'f', 0);
QString maxValueString = QString::number(m_maxValue, 'f', 0);
QFontMetrics metrics = painter->fontMetrics();
int mintextWidth = metrics.width(minValueString);
int maxtextWidth = metrics.width(maxValueString);
int textHeight = metrics.height();
//---- paint text
painter->drawText(QRectF(2, 4, mintextWidth, textHeight), minValueString);
painter->drawText(QRectF(width() - maxtextWidth - 2, 4, maxtextWidth, textHeight), maxValueString);
//----- paint label text
painter->setFont(QFont("Arial", 12));
metrics = painter->fontMetrics();
int labelWidth = metrics.width(m_label);
int labelHeight = metrics.height();
QRectF textRect = QRectF((width() / 2 - labelWidth / 2), 0, labelWidth, labelHeight);
painter->drawText(textRect, m_label);
// end
int minPos = (m_minValue - m_min) * width() / (m_max - m_min);
int maxPos = (m_maxValue - m_min) * width() / (m_max - m_min);
if (minPos <= 4) {
minPos = 4;
}
else if (minPos >= width() - 8) {
minPos = width() - 8;
}
else {}
if (maxPos <= 4) {
maxPos = 4;
}
else if (maxPos >= width() - 8) {
maxPos = width() - 8;
}
else {}
//----- paint groove
//滑块槽
paintColoredRect(QRect(4, 37, width() - 8, 2), Qt::yellow, painter);
//滑块内槽
paintColoredRect(QRect(minPos + 4, 37, maxPos - minPos, 2), QColor(51, 153, 155), painter);
//----- handle
minHandleRegion = QRect(minPos, 30, 8, 16);
maxHandleRegion = QRect(maxPos, 30, 8, 16);
//-----paint Handle
QColor minColor = (m_state == MinHandle) ? QColor(51, 153, 155) : Qt::darkGray;
QColor maxColor = (m_state == MaxHandle) ? QColor(51, 153, 155) : Qt::darkGray;
paintColoredRect(minHandleRegion, minColor, painter); //左侧滑块
paintColoredRect(maxHandleRegion, maxColor, painter); //右侧滑块
}
inline float getValidValue(float val, float min, float max)
{
float tmp = std::max(val, min);
return std::min(tmp, max);
}
void DoubleSlider::setRange(float min, float max)
{
m_min = min;
m_max = max;
if (minValue() < m_min)
setMinValue(m_min);
if (maxValue() > m_max) {
setMaxValue(m_max);
}
}
void DoubleSlider::setSingleStep(float step)
{
m_singleStep = step;
}
float DoubleSlider::minValue() const
{
return m_minValue;
}
void DoubleSlider::setMinValue(float val)
{
if (fabs(m_minValue - val) > 0.0001) {
m_minValue = val;
//emit minValueChanged(val);
}
}
float DoubleSlider::maxValue() const
{
return m_maxValue;
}
void DoubleSlider::setMaxValue(float val)
{
if (fabs(m_maxValue - val) > 0.0001) {
m_maxValue = val;
//emit maxValueChanged(val);
}
}
void DoubleSlider::setLabel(const QString& label)
{
m_label = label;
update();
}
void DoubleSlider::leaveEvent(QEvent* event)
{
QWidget::leaveEvent(event);
m_state = None;
update();
}
float DoubleSlider::minRange() const
{
return m_min;
}
float DoubleSlider::maxRange() const
{
return m_max;
}
void DoubleSlider::mousePressEvent(QMouseEvent* event)
{
if (minHandleRegion.contains(event->pos())) {
m_state = MinHandle;
}
else if (maxHandleRegion.contains(event->pos())) {
m_state = MaxHandle;
}
else {
SetPressValue(event->x());
m_state = None;
}
if (fabs(minValue() - maxValue()) < 0.001) {
if (fabs(minValue() - m_min) < 0.001) {
m_state = MaxHandle;
}
else if (fabs(minValue() - m_max) < 0.001) {
m_state = MinHandle;
}
else {}
}
update();
}
void DoubleSlider::SetPressValue(float fpos)
{
float move = fpos * (m_max - m_min) * 1.0 / width() + m_min;
abs(m_minValue - move) > abs(m_maxValue - move) ? m_state = MaxHandle : m_state = MinHandle;
if (MaxHandle == m_state)
{
float val = getValidValue(move, minValue(), m_max);
setMaxValue(val);
}
else
{
float val = getValidValue(move, m_min, maxValue());
setMinValue(val);
}
}
void DoubleSlider::SetValue(int npos)
{
float val = getValidValue(npos, m_min, maxValue());
setMinValue(val);
}
void DoubleSlider::mouseMoveEvent(QMouseEvent* event)
{
if (event->buttons() & Qt::LeftButton) {
float move = event->x() * (m_max - m_min) * 1.0 / width() + m_min;
switch (m_state) {
case MinHandle: {
float val = getValidValue(move, m_min, maxValue());
setMinValue(val);
break;
}
case MaxHandle: {
float val = getValidValue(move, minValue(), m_max);
setMaxValue(val);
break;
}
case None:default: break;
}
}
update();
}
void DoubleSlider::keyPressEvent(QKeyEvent* event)
{
QWidget::keyPressEvent(event);
if (event->key() == Qt::Key_Left) {
if (m_state == MinHandle) {
float val = getValidValue(minValue() - m_singleStep, m_min, maxValue());
setMinValue(val);
}
else if (m_state == MaxHandle) {
float val = getValidValue(maxValue() - m_singleStep, minValue(), m_max);
setMaxValue(val);
}
else {}
}
else if (event->key() == Qt::Key_Right) {
if (m_state == MinHandle) {
float val = getValidValue(minValue() + m_singleStep, m_min, maxValue());
setMinValue(val);
}
else if (m_state == MaxHandle) {
float val = getValidValue(maxValue() + m_singleStep, minValue(), m_max);
setMaxValue(val);
}
else {}
}
update();
}
4.使用小聪明,但是可以使用Qt样式
如果你之前想到使用QSlide重叠在一起,那么聪明的你怎么处理QSlider点击响应冲突和覆盖问题呢?
没错,这种情况只能使用样式和重写处理消息事件过滤。首先,处理覆盖问题,若有有什么办法能够让最上层滑轨透明,显示下层样式,直接来代码吧,这里需要注意是前后问题,如果你想QSlider1在最上层那么只能隐藏滑轨和背景,QSlider2在最下层,反之亦然。
ui.controlSlider->raise();//显示在最上层
//ui.controlSlider_2->lower();//显示在最下层
ui.controlSlider_2->setStyleSheet("QSlider::groove:horizontal{background:transparent;width:258px;height:16px;border-radius: 5px;border-image: url(:/res/Brightness_Default2x.png);background-repeat:none;}"//
"QSlider::handle:horizontal{border-radius: 20px;width:15px;height: 30px;margin-top: -8px;margin-bottom: -8px;border-image: url(:/res/effect_default2x.png);background-repeat:none;}"//滑动条上滑块
"QSlider{border: 24px solid transparent;border-left: 2px;border-right: 2px;border-radius: 15px;}");
ui.controlSlider->setStyleSheet("QSlider::groove:horizontal{background:transparent;width:258px;height:16px;border-radius: 5px;border:transparent;background-repeat:none;}"//
"QSlider::handle:horizontal{border-radius: 20px;width:15px;height: 30px;margin-top: -8px;margin-bottom: -8px;border-image: url(:/res/effect_default2x.png);background-repeat:none;}"//滑动条上滑块
"QSlider{border: 24px solid transparent;border-left: 2px;border-right: 2px;border-radius: 15px;}");
ui.controlSlider->installEventFilter(this);
ui.controlSlider_2->installEventFilter(this);
那么就剩下消息过滤,如果是QSlider1的消息,就要屏蔽QSlider2的消息响应(并不是完全屏蔽,而是根据距离去响应),关于鼠标点击距离你可以用这个方法计算,根据距离哪个近就让那个控件在最上方,记得修改样式。
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
// 如果是QSlider1的就填1的ui就可以了
int value = QStyle::sliderValueFromPosition(ui.controlSlider_2->minimum(), ui.controlSlider_2->maximum(), mouseEvent->pos().x(), ui.controlSlider_2->width());
1.需要注意QEvent::MouseMove 移动滑轨时候,有可能会出现QSlist1<QSlider2(也就是划超位置),再次去点击(如果代码里位置限制)发现会有问题,这里需要滑动完最后判断QSlider2的当前位置,如果超了要特殊处理
2.第二个问题是,当我们QSlider双滑轨切换前后位置会出现,最后的滑块没动,动的是最前面的,这是因为我们鼠标一直按着,当前界面切换过来了,但是消息处理函数还没切换过来,这里需要特殊处理一下。
5.其他滑块样式(不是双滑块的)
需求以及思路:是这样子,要求右边要有遮盖,滑动块不能超过遮盖(这个其实好做),滑块的话要用其他控件遮挡,下面直接上代码:
这样滑动条样式
ui.controlSlider->setStyleSheet("QSlider::groove:horizontal{background:transparent;width:250px;height:16px;border-radius: 5px;border-image: url(:/res/ckImage/brightness_slider2x.png);background-repeat:none;}"//
"QSlider::handle:horizontal{border-radius: 20px;width: 15px;height: 30px;margin-top: -8px;margin-bottom: -8px;border-image: url(:/res/ckImage/Brightnessbutton2x.png);background-repeat:none;}"//滑动条上滑块
"QSlider{border: 24px solid transparent;border-left: 2px;border-right: 2px;border-radius: 15px;}");
下面是遮盖处理以及思路
//当滑动条最大值不在范围内就会出现遮盖,否则不会
if (m_nMaxBv != 100) {
labelMask = new QLabel(this);
//这里是计算qlabel大小,是根据滑块算的 m_nMaxBv是允许滑动最大值
int width = (100 - m_nMaxBv) * 2.3 - (m_nMaxBv/40);
labelMask->setFixedSize(width, 10);
labelMask->adjustSize();
labelMask->setWordWrap(true);
//因为只有x轴变化,y是固定值,这里259根据上面滑动条的宽度按调出来的
labelMask->move(259 - width, 89);
//QLabel样式
labelMask->setStyleSheet("background-repeat:repeat;background-position:right;background-color:#545454;\
border-bottom-right-radius:5px;border-top-right-radius:5px;");
labelMask->show();
}
else {
if (labelMask)
labelMask->hide();
}