QSlider默认是点击一下步进一格,handle块很小的时候还点不准,在播放器等页面使用就不太友好,特此进行改进,继承QSlider,实现点哪跳转至哪, 点击任意处都可进行拖动,对水平滑动条及垂直滑动条进行了适配;
废话不多说,直接上代码:
CSlider.h
#pragma once#include <QSlider>//自定义滑块类 实现类似安卓滑动条功能, 任意点击跳转 及 任意拖选
//滑动条为垂直时候, 请设置滑块handle为滑动条宽度的一半 否则可能出现点击不太准现象
//滑动条为水平时候, 请设置滑块handle为滑动条高度的一半
class CSlider : public QSlider {Q_OBJECT
public://handleLen 0 为默认, 垂直slider:handle的高度 / 2, 水平slider: handle的宽度 / 2, 若设置了则以此值计算slider值偏移量CSlider(QWidget *parent = nullptr, uint16_t handleLen = 0);~CSlider();//设置值 , bool bNotify 是否需要信号通知void SetSliderValue(int val, bool bNotify = false);protected://鼠标按下virtual void mousePressEvent(QMouseEvent * event);//鼠标拖动virtual void mouseMoveEvent(QMouseEvent * event);//鼠标松开virtual void mouseReleaseEvent(QMouseEvent * event);private://鼠标位置转换成滑动条的值int32_t MousePostionToSliderVal(const QPoint & pos);
//signals:private:uint16_t m_handleLen; //滑块宽度
};
CSlider.cpp
#include "CSlider.h"#include <QSlider>
#include <QLabel>
#include <QStyle>#ifdef Q_OS_WIN
#pragma execution_character_set("utf-8")
#endifCSlider::CSlider(QWidget * parent, uint16_t handleLen): QSlider(parent), m_handleLen(handleLen) {
}CSlider::~CSlider() {}
//设置值 , bool bNotify 是否需要信号通知值滑块移动了
void CSlider::SetSliderValue(int val, bool bNotify) {setSliderPosition(val);if (bNotify)emit sliderMoved(val);
}void CSlider::mousePressEvent(QMouseEvent * event) {if (event->button() != Qt::LeftButton)return;setSliderDown(true);
}static bool bIsMove = false;
void CSlider::mouseMoveEvent(QMouseEvent * event) {bIsMove = true;int32_t pos = MousePostionToSliderVal(event->pos());if (pos != sliderPosition()) {setSliderPosition(pos);emit sliderMoved(pos);}
}void CSlider::mouseReleaseEvent(QMouseEvent * event) {setSliderDown(false);if (!isEnabled() || event->button() != Qt::LeftButton) {bIsMove = false;return;}if (bIsMove) {QSlider::mouseReleaseEvent(event);bIsMove = false;} else {int32_t pos = MousePostionToSliderVal(event->pos());if (pos != sliderPosition()) {setSliderPosition(pos);emit sliderMoved(pos);}}
}//鼠标位置转换成滑动条的值
int32_t CSlider::MousePostionToSliderVal(const QPoint & pos) {int32_t duration = maximum() - minimum();int32_t sliderPos = 0;qreal mousePos = 0;uint16_t hanleLen = 0;if (Qt::Vertical == orientation()) {//设置了handle高度 则以m_handleLen为准, 如无设置 则以宽度一半为handleLenhanleLen = m_handleLen ? m_handleLen : width() / 2.0;mousePos = (qreal)(pos.y() - hanleLen / 2);if (0 > mousePos)mousePos = 0;else if (mousePos > height() - hanleLen)mousePos = (qreal)(height() - hanleLen);sliderPos = maximum() - duration * (mousePos / (height() - hanleLen));} else {//设置了handle宽度 则以m_handleLen为准, 如无设置 则以高度度一半为handleLenhanleLen = m_handleLen ? m_handleLen : height() / 2.0;mousePos = (qreal)(pos.x() - hanleLen / 2);if (0 > mousePos)mousePos = 0;else if (pos.x() > width() - hanleLen)mousePos = (qreal)(width() - hanleLen);sliderPos = minimum() + duration * (mousePos / (width() - hanleLen));}return sliderPos;
}
使用:
CSlider * m_pSlider;m_pSlider = new CSlider(this, 30);
m_pSlider->setFixedSize(60, 480);
m_pSlider->setContentsMargins(0, 0, 0, 0);
m_pSlider->setOrientation(Qt::Vertical);
m_pSlider->setRange(100, 200);
m_pSlider->setSingleStep(1);
m_pSlider->setValue(100);
m_pSlider->setTickPosition(QSlider::TicksBothSides);
使用方法和QSlider并无多大区别;
有个值得注意的地方,构造函数第二个参数, handLen为滑块大小,需配合QSS handle:vertical->height属性 或 handle:horizontal ->width属性结合使用,以此进行偏移计算sliderpostion位置
附上QSS供参考:
QSlider#CSlider::groove:horizontal{background:#4b4b4b;height:6px;border-radius:5px;
}
QSlider#CSlider::add-page:horizontal{background:#c5c5c5;height:6px;border-radius:5px;
}
QSlider#CSlider::sub-page:horizontal{background:rgba(2, 183, 196, 0.75);height:6px;border-radius:5px;
}
QSlider#CSlider::handle:horizontal{width:25px;margin-top: -17px;margin-bottom: -17px;border-radius: 5px;background: rgba(255, 255, 255, 0.85);
}
QSlider#CSlider::handle:horizontal:pressed, QSlider#CSlider::handle:horizontal:hover{width:25px;border-radius:5px;background: #FFFFFF;
}
QSlider#CSlider::add-page:horizontal:disabled{background:#616161;
}
QSlider#CSlider::sub-page:horizontal:disabled{background:rgba(141, 141, 141, 0.75);
}
QSlider#CSlider::handle:horizontal:disabled{background: rgba(112, 112, 112, 0.85);
}