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")
#endif
CSlider::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为准, 如无设置 则以宽度一半为handleLen
hanleLen = 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为准, 如无设置 则以高度度一半为handleLen
hanleLen = m_handleLen ? m_handleLen : height() / 2.0;
mousePos = (qreal)(pos.x() - hanleLen / 2);
if (0 > mousePos)
mousePos = 0;
else if (mousePos > width() - hanleLen)
mousePos = (qreal)(width() - hanleLen);
sliderPos = minimum() + duration * (mousePos / (width() - hanleLen));
}
return sliderPos;
}
使用:
CSlider * m_pSlider;
m_pSlider = new CSlider(this, 25);
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);
}