废话不多说,先上效果图,下面贴出全部代码,有需求自行修改。
1. RulerSlider.h文件
#ifndef RULERSLIDER_H
#define RULERSLIDER_H
#define SMALL_Y 5 //小刻度
#define MIDDLE_Y 7 //中刻度
#define BIG_Y 10 //大刻度
#define DIFFERVALUE 1 //最小差值(最大值与最小值的差)
#define SIDEDISTANCE 10 //尺子距离左边的距离
#define SIDEDISTANCER 50 //尺子距离右边的距离
#define HANDLEWIDTH 10 //滑块的宽度
#define HANDLEHEIGHT 15 //滑块的高度
#define MININTERVSL 10 //最小刻度之间距离
#define MAXINTERVSL 20 //最大刻度之间距离
#define DISTANCEMOUSE 20 //鼠标悬停距离箭头的位置
class RulerSlider : public QSlider
{
public:
RulerSlider(QWidget *parent = nullptr);
~RulerSlider();
//刻度之间的距离
qreal sliderInterval = 1;
//显示刻度值
QLabel *valueLabel;
//滑块
QLabel *handleLabel;
//鼠标是否点击
bool mouseIsClick = false;
//设置控件的范围
void setRulerSliderRange(int min,int max);
//设置当前值
void setRulerSliderValue(int value);
private:
//绘制尺子背景
void drawRulerBackgroud(QPainter *painter);
//绘制刻度线与值
void drawSliderMark(QPainter *painter);
//根据坐标位置计算当前值
void eventPosGetValue(QMouseEvent *ev);
//鼠标事件
void mouseFilterEvent(QMouseEvent *event);
protected:
//重新绘制
void paintEvent(QPaintEvent *);
//过滤器
bool eventFilter(QObject *watched,QEvent *event);
};
#endif // RULERSLIDER_H
2.RulerSlider.cpp 文件
#include "RulerSlider.h"
#include "QPainter"
#include "math.h"
RulerSlider::RulerSlider(QWidget *parent):QSlider(parent)
{
//注册过滤器
installEventFilter(this);
//鼠标事件追踪
setMouseTracking(true);
//显示当前值label
valueLabel = new QLabel(this);
valueLabel->setStyleSheet("background-color: rgb(0, 0, 0);font-size:14px;color:white;border:1px solid black");
valueLabel->setAlignment(Qt::AlignCenter);
valueLabel->hide();
//滑块
handleLabel = new QLabel(this);
handleLabel->setFixedSize(20,15);
handleLabel->raise();
QImage image,result;
image.load(":/images/handle.png");//temppath为图片的路径
result = image.scaled(handleLabel->width(), handleLabel->height(),Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//放缩图片,以固定大小显示
handleLabel->setPixmap(QPixmap::fromImage(result));//在Label控件上显示图片
}
RulerSlider::~RulerSlider()
{
}
/**
* 绘制
* @brief RulerSlider::paintEvent
*/
void RulerSlider::paintEvent(QPaintEvent *)
{
QPainter painter;
painter.begin(this);
//抗锯齿
painter.setRenderHint(QPainter::Antialiasing);
drawRulerBackgroud(&painter);
drawSliderMark(&painter);
painter.end();
}
/**
* 绘制尺子背景
* @brief RulerSlider::drawRulerBackgroud
* @param painter
*/
void RulerSlider::drawRulerBackgroud(QPainter *painter)
{
QPointF topLeftPot3(0,0);
QPointF bottomRightPot3(width(),height());
painter->setPen(Qt::white);
painter->setBrush(QColor(61,84,110));
painter->drawRect(QRectF(topLeftPot3,bottomRightPot3));
}
/**
* 绘制刻度与值
* @brief RulerSlider::drawSliderMark
* @param painter
*/
void RulerSlider::drawSliderMark(QPainter *painter)
{
painter->setPen(Qt::gray);
painter->setBrush(QColor(128,128,128));
//计算刻度之间的间隔最小为10
int dis = maximum()-minimum();
//绘制横坐标开始起点
qreal startX = SIDEDISTANCE;
for (uint16_t i=minimum();i<=(minimum()+dis/singleStep());i++) {
//偶数
if(i%2 == 0 && i%5 == 0){
painter->drawRect(QRectF(startX,0,0.1,BIG_Y));
//绘制刻度值
float value = round(minimum()+((i-minimum())*singleStep()));
QString strValue = tr("%1").arg(value);
int fontWidth = fontMetrics().width(strValue)/2;
painter->drawText(QPointF(startX-fontWidth,BIG_Y+15),strValue);
}else {
if(i%5 == 0){
painter->drawRect(QRectF(startX,0,0.1,MIDDLE_Y));
}else{
painter->drawRect(QRectF(startX,0,0.1,SMALL_Y));
}
}
startX+=sliderInterval;
}
}
/**
* 根据鼠标位置获取当前值
* @brief RulerSlider::eventPosGetValue
* @param ev
*/
void RulerSlider::eventPosGetValue(QMouseEvent *ev)
{
//光标所在矩形范围
double posWidth = (double)width()-SIDEDISTANCER-SIDEDISTANCE;
//鼠标光标位置
double xpos = ev->pos().x();
if(xpos >=SIDEDISTANCE&&xpos<=width()-SIDEDISTANCER){
//根据光标计算
double posValue = (xpos-SIDEDISTANCE)/posWidth;
int value =round(posValue * (maximum()-minimum()) + minimum());
handleLabel->move(xpos-handleLabel->width()/2,0);
qDebug()<<"结果值"< setValue(value); } } /** * 设置slider范围 * @brief RulerSlider::setRulerSliderRange * @param min * @param max */ void RulerSlider::setRulerSliderRange(int min, int max) { //当设置的最小值为负数或0时,设置最小值为0 int minNum = min; int maxNum = max; if(min<=0){ minNum = 0; } //当最大值与最小值之间差值 if(max-min <= DIFFERVALUE){ maxNum = min+DIFFERVALUE; } qDebug()<<"滑动条"< setMaximum(maxNum); setMinimum(minNum); if(value()>minNum){ int dis = maxNum-minNum; sliderInterval = (float)(width()-SIDEDISTANCE-SIDEDISTANCER)/(dis/singleStep()); double pos = ((value()-minNum)/singleStep())*sliderInterval+SIDEDISTANCE; handleLabel->move(pos-handleLabel->width()/2,0); }else { handleLabel->move(SIDEDISTANCE-handleLabel->width()/2,0); } update(); } /** * 设置当前值 * @brief RulerSlider::setRulerSliderValue * @param value */ void RulerSlider::setRulerSliderValue(int value) { int dis = maximum()-minimum(); sliderInterval = (float)(width()-SIDEDISTANCE-SIDEDISTANCER)/(dis/singleStep()); double pos = ((value-minimum())/singleStep())*sliderInterval+SIDEDISTANCE; handleLabel->move(pos-handleLabel->width()/2,0); setValue(value); } /** * 鼠标移动事件 * 当mouseIsClick为true时拖动false悬停 * @brief RulerSlider::mouseFilterEvent * @param event */ void RulerSlider::mouseFilterEvent(QMouseEvent *event) { //鼠标光标位置 double xpos = event->pos().x(); if(xpos >=SIDEDISTANCE&&xpos<=width()-SIDEDISTANCER){ if(mouseIsClick){ handleLabel->move(xpos-handleLabel->width()/2,0); if(valueLabel->isVisible()){ valueLabel->hide(); } }else { //光标所在矩形范围 double posWidth = (double)width()-SIDEDISTANCER-SIDEDISTANCE; //根据光标计算 double posValue = (xpos-SIDEDISTANCE)/posWidth; int value =round(posValue * (maximum()-minimum()) + minimum()); if(valueLabel->isHidden()){ valueLabel->show(); } if(value >= minimum() && value <= maximum()){ valueLabel->setText(QString::number(value)); valueLabel->adjustSize(); valueLabel->move(xpos+DISTANCEMOUSE,height()-valueLabel->height()); valueLabel->raise(); } } } } /** * 事件过滤 * @brief RulerSlider::eventFilter * @param watched * @param event * @return */ bool RulerSlider::eventFilter(QObject *watched, QEvent *event) { //鼠标事件 QMouseEvent *mouseEvent = static_cast(event); //鼠标离开 if(QEvent::HoverLeave == event->type()&&!valueLabel->isHidden()){ valueLabel->hide(); } //鼠标悬停与拖动 if(QEvent::HoverMove == event->type()){ mouseFilterEvent(mouseEvent); } //鼠标点击事件 if(QEvent::MouseButtonPress == event->type()){ if(mouseEvent->button() & Qt::LeftButton){ mouseIsClick = true; } } //鼠标释放事件 if(QEvent::MouseButtonRelease == event->type()){ //注意应先调用父类的鼠标点击处理事件,这样可以不影响拖动的情况 QSlider::mouseReleaseEvent(mouseEvent); eventPosGetValue(mouseEvent); mouseIsClick = false; } return QSlider::eventFilter(watched,event); } 3. 图片文件 4. 使用 RulerSlider *slider = new RulerSlider(this); slider->setFixedSize(this->width(),50); slider->setSingleStep(1); slider->setRulerSliderRange(0,100); slider->setRulerSliderValue(50); QObject::connect(slider,SIGNAL(valueChanged(int)),this,SLOT(sliderValueChanged(int)));