Qt 自定义尺子控件

废话不多说,先上效果图,下面贴出全部代码,有需求自行修改。

截图

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. 图片文件


handle.png


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)));

你可能感兴趣的:(Qt 自定义尺子控件)