Qt 自定义控件 标尺控件 QLsRuler

一、应用案例

在这里插入图片描述

二、样式展示

在这里插入图片描述
注:录制界面为测试界面,实际标尺样式为上半部分

三、源码

qls_qss_global.h

#ifndef QLS_QSS_GLOBAL_H
#define QLS_QSS_GLOBAL_H

/* ----- qss属性封装 ----- */
// val, get, set, sig_changed, Q_PROPERTY
#define QLS_PROPERTY(var_, type_)                    \
private:                                             \
    type_ var_;                                      \
                                                     \
public:                                              \
    inline type_ get_##var_() const { return var_; } \
                                                     \
Q_SIGNALS:                                           \
    void sig_##var_##changed();                      \
                                                     \
public Q_SLOTS:                                      \
    void set_##var_(type_ var)                       \
    {                                                \
        var_ = var;                                  \
        update();                                    \
        emit sig_##var_##changed();                  \
    }                                                \
                                                     \
public:                                              \
    Q_PROPERTY(type_ var_ READ get_##var_ WRITE set_##var_)

/* ----- 常用样式组合 ----- */
// normal, hover, check
#define QLS_PROPERTY_NHC(var_, type_)  \
    QLS_PROPERTY(var_##normal_, type_) \
    QLS_PROPERTY(var_##hover_, type_)  \
    QLS_PROPERTY(var_##check_, type_)

// normal, press
#define QLS_PROPERTY_NP(var_, type_)   \
    QLS_PROPERTY(var_##normal_, type_) \
    QLS_PROPERTY(var_##press_, type_)

// normal, hover, press, check, disable
#define QLS_PROPERTY_NHPCD(var_, type_) \
    QLS_PROPERTY(var_##normal_, type_)  \
    QLS_PROPERTY(var_##hover_, type_)   \
    QLS_PROPERTY(var_##press_, type_)   \
    QLS_PROPERTY(var_##check_, type_)   \
    QLS_PROPERTY(var_##disable_, type_)


#endif // QLS_QSS_GLOBAL_H

qls_ruler.h

#ifndef QLSRULER_H
#define QLSRULER_H

#include <QWidget>

#include "qls_qss_global.h"

class QLabel;

class QLsRuler : public QWidget
{
    Q_OBJECT

    Q_ENUMS(ScaleLabelPosition)
    Q_ENUMS(RulerDirection)
    Q_ENUMS(ScaleDirection)
    Q_ENUMS(RulerType)
    Q_ENUMS(ScaleType)

public:
#if 0
    // 刻度等级
    enum ScaleLevel{
        ScaleLevel_Unit = 0,                // 刻度单位
        ScaleLevel_Label = 1,               // 刻度值
    };

    // 刻度范围
    enum ScaleRange{
        ScaleRange_All = 0,                 // 整体范围
        ScaleRange_valid = 1,               // 有效范围,可移动范围
    };
#endif

    // 刻度条文字位置
    enum ScaleLabelPosition{
        ScaleLabelPosition_Inside = 0,      // 里面
        ScaleLabelPosition_Outside = 1,     // 外面
    };

    // 标尺方向
    enum RulerDirection{
        RulerDirection_West = 0,            // 上北
        RulerDirection_North = 1,           // 右东
        RulerDirection_South = 2,           // 下南
        RulerDirection_East = 3,            // 左西
    };

    // 刻度方向
    enum ScaleDirection{
        ScaleDirection_Left_To_Right = 0,   // 从左到右
        ScaleDirection_Right_To_Left = 1,   // 从右到左
    };

    // 标尺类型
    enum RulerType{
        RulerType_Scale = 0,                // 只有刻度
        RulerType_Cursor = 1,               // 游标标尺
        RulerType_Line = 2,                 // 线性标尺
        RulerType_Progress = 3,             // 进度标尺
        RulerType_Slide = 4,                // 滑动标尺
    };

    // 刻度类型
    enum ScaleType{
        ScaleType_Value = 0,                // 根据数值绘制
        ScaleType_Number = 1,               // 根据刻度个数绘制
    };

public:
    explicit QLsRuler(QWidget *parent = nullptr);

protected:
    void paintEvent(QPaintEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *evnet) override;
    void mouseMoveEvent(QMouseEvent *event) override;

private:
    // 更新最小尺寸
    void updateMinimumSize(QPainter *painter);

    // 进度标尺 绘制进度背景色
    void drawProgress(QPainter *painter);
    // 绘制刻度尺颜色
    void drawScaleRangeColor(QPainter *painter);
    // 绘制刻度
    void drawScale(QPainter *painter);
    // 绘制标签
    void drawLabel(QPainter *painter);
    // 线性标尺 绘制进度线条
    void drawLine(QPainter *painter);
    // 游标标尺 滑动标尺 绘制游标
    void drawCursor(QPainter *painter);

    // 获取旋转后的 总区域
    QRect getRotateRectAll(QPainter *painter);
    // 获取旋转后的 实际内容区域 默认居中
    QRect getRotateRectTrue(QPainter *painter);
    // 获取旋转后的 刻度条区域
    QRect getRotateRectScale(QPainter *painter);
    // 获取旋转后的 标签区域
    QRect getRotateRectLabel(QPainter *painter);

    // 旋转前后坐标转换
    QPointF getRotatePoint(const QPointF &p0, const QPointF &p1, double a);

private:
    // 游标提示值
    QLabel *cursor_label_;

    // 鼠标状态
    bool press_{false};
    bool is_move_triangle_{false};
    QPointF triangle_pos_;

    // 偏移坐标、旋转角度
    QPointF translate_point_;
    qreal rotate_angle_;

    // 游标
    QPolygonF triangle_{QVector<QPointF>(3, QPointF(0, 0))};

    // 内边距
    QLS_PROPERTY(padding_top_, double)
    QLS_PROPERTY(padding_right_, double)
    QLS_PROPERTY(padding_bottom_, double)
    QLS_PROPERTY(padding_left_, double)
    // 文字到刻度条的间距
    QLS_PROPERTY(scale_label_space_, double)

    // 标尺类型
    QLS_PROPERTY(ruler_type_, RulerType)

    // 标尺方向
    QLS_PROPERTY(ruler_direction_, RulerDirection)
    // 刻度方向
    QLS_PROPERTY(scale_direction_, ScaleDirection)

    // 刻度值
    QLS_PROPERTY(scale_value_, double)
    QLS_PROPERTY(scale_unit_value_, double)
    QLS_PROPERTY(scale_label_value_, double)
    // 刻度类型
    QLS_PROPERTY(scale_type_, ScaleType)

    // 刻度范围
    QLS_PROPERTY(scale_range_all_min_, double)
    QLS_PROPERTY(scale_range_all_max_, double)
    QLS_PROPERTY(scale_range_valid_enabled_, bool)
    QLS_PROPERTY(scale_range_valid_min_, double)
    QLS_PROPERTY(scale_range_valid_max_, double)
    // 刻度条范围颜色
    QLS_PROPERTY(scale_range_all_color_, QBrush)
    QLS_PROPERTY(scale_range_valid_color_, QBrush)
    // 刻度条范围背景颜色
    QLS_PROPERTY(scale_range_all_bgcolor_, QBrush)
    QLS_PROPERTY(scale_range_valid_bgcolor_, QBrush)

    // 刻度条尺寸
    QLS_PROPERTY(scale_unit_size_, QSize)
    QLS_PROPERTY(scale_label_size_, QSize)
    // 刻度条厚度
    QLS_PROPERTY(scale_thickness_, double)

    // 是否显示刻度值标签
    QLS_PROPERTY(scale_label_visiable_, bool)
    // 刻度值标签位置
    QLS_PROPERTY(scale_label_position_, ScaleLabelPosition)

    // 是否显示游标
    QLS_PROPERTY(cursor_visiable_, bool)
    // 游标颜色
    QLS_PROPERTY(cursor_color_, QBrush)
    // 游标边长
    QLS_PROPERTY(cursor_side_, double)
    // 是否显示游标提示值
    QLS_PROPERTY(cursor_label_visiable_, bool)
};

#endif // QLSRULER_H

qls_ruler.cpp

#include "qls_ruler.h"

#include <cmath>

#include <QPainter>
#include <QMouseEvent>
#include <QtMath>
#include <QToolTip>
#include <QLabel>
#include <QMap>

QLsRuler::QLsRuler(QWidget *parent) : QWidget(parent)
{
    // 游标旁提示值
    cursor_label_ = new QLabel(this);
    cursor_label_->setFixedSize(40, 20);
    cursor_label_->setAlignment(Qt::AlignCenter);
    cursor_label_->hide();

    // 内边距
    padding_top_ = 5;
    padding_right_ = 5;
    padding_bottom_ = 5;
    padding_left_ = 5;
    // 文字到刻度条的间距
    scale_label_space_ = 5;

    // 标尺类型
    ruler_type_ = RulerType_Cursor;
    connect(this, &QLsRuler::sig_ruler_type_changed, [=]{
        switch (get_ruler_type_()) {
        case RulerType_Scale:
            cursor_visiable_ = false;
            scale_label_visiable_ = false;
            break;
        case RulerType_Cursor:
            cursor_visiable_ = true;
            scale_label_visiable_ = true;
            break;
        case RulerType_Line:
            cursor_visiable_ = false;
            scale_label_visiable_ = true;
            break;
        case RulerType_Progress:
            cursor_visiable_ = false;
            scale_label_visiable_ = true;
            break;
        case RulerType_Slide:
            cursor_visiable_ = true;
            scale_label_visiable_ = true;
            break;
        }
    });

    // 标尺方向
    ruler_direction_ = RulerDirection_West;
    // 刻度方向
    scale_direction_ = ScaleDirection_Left_To_Right;

    // 刻度值
    scale_value_ = 20;
    scale_unit_value_ = 3;
    scale_label_value_ = 1;
    // 刻度类型
    scale_type_ = ScaleType_Number;

    // 刻度范围
    scale_range_all_min_ = 0;
    scale_range_all_max_ = 100;
    scale_range_valid_enabled_ = true;
    scale_range_valid_min_ = 0;
    scale_range_valid_max_ = 100;
    // 刻度条范围颜色
    scale_range_all_color_ = QColor(204, 204, 204);
    scale_range_valid_color_ = QColor(129 , 126, 121);
    // 刻度条范围背景颜色
    scale_range_all_bgcolor_ = QColor(238, 238, 238);
    scale_range_valid_bgcolor_ = QColor(0, 255, 0);

    // 刻度条尺寸
    scale_unit_size_ = QSize(3, 5);
    scale_label_size_ = QSize(3, 10);
    // 刻度条厚度
    scale_thickness_ = 3;

    // 刻度值标签位置
    scale_label_position_ = ScaleLabelPosition_Outside;

    // 是否显示游标
    cursor_visiable_ = true;
    // 游标颜色
    cursor_color_ = QColor(255, 129, 0);
    // 游标边长
    cursor_side_ = 15;
    // 是否显示游标提示值
    cursor_label_visiable_ = false;
}

void QLsRuler::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);    // 反锯齿

    drawProgress(&painter);
    drawScaleRangeColor(&painter);
    drawScale(&painter);
    drawLabel(&painter);
    drawLine(&painter);
    drawCursor(&painter);

    updateMinimumSize(&painter);

    QWidget::paintEvent(event);
}

void QLsRuler::mousePressEvent(QMouseEvent *event)
{
    press_ = true;

    // 按下游标,记录当前坐标,进入拖拽状态
    if(get_ruler_type_() == RulerType_Slide &&
            triangle_.containsPoint(
                getRotatePoint(
                    translate_point_, event->pos(), rotate_angle_
                    ), Qt::OddEvenFill)){
        triangle_pos_ = event->pos();
        is_move_triangle_ = true;

        // 游标旁显示当前值
        if(cursor_label_visiable_ && cursor_label_->isHidden()){
            cursor_label_->show();
            cursor_label_->setText(QString::number(get_scale_value_(), 'f', 0));
            if(event->pos().x() + 10 + cursor_label_->width() >= width()){
                cursor_label_->move(event->pos() - QPoint(-cursor_label_->width() - 10, 0));
            } else {
                cursor_label_->move(event->pos() + QPoint(10, 0));
            }
        }
    }

    update();
    QWidget::mousePressEvent(event);
}

void QLsRuler::mouseReleaseEvent(QMouseEvent *event)
{
    press_ = false;
    is_move_triangle_ = false;

    // 隐藏游标提示值
    if(cursor_label_visiable_ && cursor_label_->isVisible()){
        cursor_label_->hide();
    }

    update();
    QWidget::mouseReleaseEvent(event);
}

void QLsRuler::mouseMoveEvent(QMouseEvent *event)
{
    // 拖拽
    if(is_move_triangle_){
        // 横向推拽
        if(get_ruler_direction_() == RulerDirection_West || get_ruler_direction_() == RulerDirection_South){
            double x = event->pos().x() - triangle_pos_.x();
            QPainter painter(this);
            scale_value_ = get_scale_value_() +
                    (get_ruler_direction_() == RulerDirection_West ||
                     get_ruler_direction_() == RulerDirection_North ? 1.0 : -1.0) *
                    (get_scale_direction_() == ScaleDirection_Left_To_Right ? 1.0 : -1.0) *
                    x * (get_scale_range_all_max_() - get_scale_range_all_min_()) /
                    getRotateRectScale(&painter).width();
        }
        // 竖向拖拽
        else {
            double y = event->pos().y() - triangle_pos_.y();
            QPainter painter(this);
            scale_value_ = get_scale_value_() +
                    (get_ruler_direction_() == RulerDirection_West ||
                     get_ruler_direction_() == RulerDirection_North ? 1.0 : -1.0) *
                    (get_scale_direction_() == ScaleDirection_Left_To_Right ? 1.0 : -1.0) *
                    y * (get_scale_range_all_max_() - get_scale_range_all_min_()) /
                    getRotateRectScale(&painter).width();
        }
        // 记录上次坐标
        triangle_pos_ = event->pos();

        // 游标旁显示当前值
        if(cursor_label_visiable_ && cursor_label_->isVisible()){
            cursor_label_->setText(QString::number(get_scale_value_(), 'f', 0));
            if(event->pos().x() + 10 + cursor_label_->width() >= width()){
                cursor_label_->move(event->pos() - QPoint(cursor_label_->width() + 10, 0));
            } else {
                cursor_label_->move(event->pos() + QPoint(10, 0));
            }
        }

        // 更新游标
        update();
        return;
    }

    QWidget::mouseMoveEvent(event);
}

void QLsRuler::updateMinimumSize(QPainter *painter)
{
    painter->save();
    switch (get_ruler_direction_()) {
    case RulerDirection_West:
    case RulerDirection_South:
        setMinimumWidth(0);
        setMinimumHeight(getRotateRectTrue(painter).adjusted(
                             -get_padding_left_(), -get_padding_top_(),
                             get_padding_right_(), get_padding_bottom_()).height());
        break;
    case RulerDirection_East:
    case RulerDirection_North:
        setMinimumHeight(0);
        setMinimumWidth(getRotateRectTrue(painter).adjusted(
                            -get_padding_left_(), -get_padding_top_(),
                            get_padding_right_(), get_padding_bottom_()).width());
        break;
    default: break;
    }
    painter->restore();
}

void QLsRuler::drawProgress(QPainter *painter)
{
    if(get_ruler_type_() != RulerType_Progress){
        return;
    }

    painter->save();
    painter->setPen(Qt::NoPen);

    QRect rect_all = getRotateRectAll(painter);

    // 从左到右
    if(get_scale_direction_() == ScaleDirection_Left_To_Right){
        // 绘制刻度条整体背景颜色
        painter->setBrush(get_scale_range_all_bgcolor_());
        painter->drawRect(rect_all.adjusted(rect_all.width() * get_scale_value_() / (get_scale_range_all_max_() - get_scale_range_all_min_()), 0, 0, 0));

        // 绘制刻度条有效背景颜色
        painter->setBrush(get_scale_range_valid_bgcolor_());
        painter->drawRect(rect_all.adjusted(0, 0, -rect_all.width() * (1 - get_scale_value_() / (get_scale_range_all_max_() - get_scale_range_all_min_())), 0));
    }
    // 从右到左
    else {
        // 绘制刻度条整体背景颜色
        painter->setBrush(get_scale_range_all_bgcolor_());
        painter->drawRect(rect_all.adjusted(0, 0, -rect_all.width() * get_scale_value_() / (get_scale_range_all_max_() - get_scale_range_all_min_()), 0));

        // 绘制刻度条有效背景颜色
        painter->setBrush(get_scale_range_valid_bgcolor_());
        painter->drawRect(rect_all.adjusted(rect_all.width() * (1 - get_scale_value_() / (get_scale_range_all_max_() - get_scale_range_all_min_())), 0, 0, 0));
    }

    painter->restore();
}

void QLsRuler::drawScaleRangeColor(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    QRect rect_scale = getRotateRectScale(painter);

    // 绘制刻度条整体颜色
    painter->setBrush(get_scale_range_all_color_());
    painter->drawRect(rect_scale.adjusted(0, rect_scale.height() - get_scale_thickness_(), 0, 0));

    painter->setBrush(get_scale_range_valid_color_());
    // 从左到右
    if(get_scale_direction_() == ScaleDirection_Left_To_Right) {
        // 绘制刻度条有效颜色
        painter->drawRect(
                    rect_scale.adjusted(
                        rect_scale.width() * (get_scale_range_valid_min_() - get_scale_range_all_min_()) /
                        (get_scale_range_all_max_() - get_scale_range_all_min_()),
                        rect_scale.height() - get_scale_thickness_(),
                        -rect_scale.width() * (get_scale_range_all_max_() - get_scale_range_valid_max_()) /
                        (get_scale_range_all_max_() - get_scale_range_all_min_()),
                        0));
    }
    // 从右到左
    else {
        // 绘制刻度条有效颜色
        painter->drawRect(
                    rect_scale.adjusted(
                        rect_scale.width() * (get_scale_range_all_max_() - get_scale_range_valid_max_()) /
                        (get_scale_range_all_max_() - get_scale_range_all_min_()),
                        rect_scale.height() - get_scale_thickness_(),
                        -rect_scale.width() * (get_scale_range_valid_min_() - get_scale_range_all_min_()) /
                        (get_scale_range_all_max_() - get_scale_range_all_min_()),
                        0));

    }

    painter->restore();
}

void QLsRuler::drawScale(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(get_scale_range_all_color_());

    QRect rect_scale = getRotateRectScale(painter);

    // 绘制刻度
    // 绘制两侧刻度
    painter->drawRect(rect_scale.left() - get_scale_label_size_().width() / 2, rect_scale.top(), get_scale_label_size_().width(), get_scale_label_size_().height());
    painter->drawRect(rect_scale.right() - get_scale_label_size_().width() / 2, rect_scale.top(),
                      get_scale_label_size_().width(), get_scale_label_size_().height());

    // 根据刻度值绘制
    if(get_scale_type_() == ScaleType_Value){
        // 从左到右
        if(get_scale_direction_() == ScaleDirection_Left_To_Right){
            for(int i = get_scale_range_all_min_() + get_scale_unit_value_();
                i < get_scale_range_all_max_(); i += get_scale_unit_value_()){
                // 绘制标签刻度
                if(i % QString::number(get_scale_label_value_()).toInt() == 0){
                    painter->drawRect(rect_scale.left() + rect_scale.width() *
                                      (i - get_scale_range_all_min_()) /
                                      (get_scale_range_all_max_() - get_scale_range_all_min_())
                                      - get_scale_label_size_().width() / 2,
                                      rect_scale.top(),
                                      get_scale_label_size_().width(), get_scale_label_size_().height());
                }
                // 绘制单位刻度
                else if(i % QString::number(get_scale_unit_value_()).toInt() == 0) {
                    painter->drawRect(rect_scale.left() + rect_scale.width() *
                                      (i - get_scale_range_all_min_()) /
                                      (get_scale_range_all_max_() - get_scale_range_all_min_())
                                      - get_scale_unit_size_().width() / 2,
                                      rect_scale.top() + get_scale_label_size_().height() - get_scale_unit_size_().height(),
                                      get_scale_unit_size_().width(), get_scale_unit_size_().height());
                }
            }
        }
        // 从右到左
        else {
            for(int i = get_scale_range_all_min_() + get_scale_unit_value_();
                i < get_scale_range_all_max_(); i += get_scale_unit_value_()){
                // 绘制标签刻度
                if(i % QString::number(get_scale_label_value_()).toInt() == 0){
                    painter->drawRect(rect_scale.left() + rect_scale.width() *
                                      (get_scale_range_all_max_() - i) /
                                      (get_scale_range_all_max_() - get_scale_range_all_min_())
                                      - get_scale_label_size_().width() / 2,
                                      rect_scale.top(),
                                      get_scale_label_size_().width(), get_scale_label_size_().height());
                }
                // 绘制单位刻度
                else if(i % QString::number(get_scale_unit_value_()).toInt() == 0) {
                    painter->drawRect(rect_scale.left() + rect_scale.width() *
                                      (get_scale_range_all_max_() - i) /
                                      (get_scale_range_all_max_() - get_scale_range_all_min_())
                                      - get_scale_unit_size_().width() / 2,
                                      rect_scale.top() + get_scale_label_size_().height() - get_scale_unit_size_().height(),
                                      get_scale_unit_size_().width(), get_scale_unit_size_().height());
                }
            }
        }
    }
    // 根据刻度个数绘制
    else {
        // 从左到右
        if(get_scale_direction_() == ScaleDirection_Left_To_Right){
            auto num = get_scale_unit_value_() * (get_scale_label_value_() + 1) + get_scale_label_value_();
            auto unit_val = (get_scale_range_all_max_() - get_scale_range_all_min_()) / (num + 1);
            for(int index = 1; index <= num; index++){
                auto i = index * unit_val + get_scale_range_all_min_();
                // 绘制标签刻度
                if(index % (QString::number(get_scale_unit_value_()).toInt() + 1) == 0){
                    painter->drawRect(rect_scale.left() + rect_scale.width() *
                                      (i - get_scale_range_all_min_()) /
                                      (get_scale_range_all_max_() - get_scale_range_all_min_())
                                      - get_scale_label_size_().width() / 2,
                                      rect_scale.top(),
                                      get_scale_label_size_().width(), get_scale_label_size_().height());
                }
                // 绘制单位刻度
                else {
                    painter->drawRect(rect_scale.left() + rect_scale.width() *
                                      (i - get_scale_range_all_min_()) /
                                      (get_scale_range_all_max_() - get_scale_range_all_min_())
                                      - get_scale_unit_size_().width() / 2,
                                      rect_scale.top() + get_scale_label_size_().height() - get_scale_unit_size_().height(),
                                      get_scale_unit_size_().width(), get_scale_unit_size_().height());
                }
            }
        }
        // 从右到左
        else {
            auto num = get_scale_unit_value_() * (get_scale_label_value_() + 1) + get_scale_label_value_();
            auto unit_val = (get_scale_range_all_max_() - get_scale_range_all_min_()) / (num + 1);
            for(int index = 1; index <= num; index++){
                auto i = index * unit_val + get_scale_range_all_min_();
                // 绘制标签刻度
                if(index % (QString::number(get_scale_unit_value_()).toInt() + 1) == 0){
                    painter->drawRect(rect_scale.left() + rect_scale.width() *
                                      (get_scale_range_all_max_() - i) /
                                      (get_scale_range_all_max_() - get_scale_range_all_min_())
                                      - get_scale_label_size_().width() / 2,
                                      rect_scale.top(),
                                      get_scale_label_size_().width(), get_scale_label_size_().height());
                }
                // 绘制单位刻度
                else {
                    painter->drawRect(rect_scale.left() + rect_scale.width() *
                                      (get_scale_range_all_max_() - i) /
                                      (get_scale_range_all_max_() - get_scale_range_all_min_())
                                      - get_scale_unit_size_().width() / 2,
                                      rect_scale.top() + get_scale_label_size_().height() - get_scale_unit_size_().height(),
                                      get_scale_unit_size_().width(), get_scale_unit_size_().height());
                }
            }
        }
    }

    painter->restore();
}

bool operator<(const QPointF &p1, const QPointF &p2){
    return p1.x() == p2.x() ? p1.y() < p2.y() : p1.x() < p2.x();
}

void QLsRuler::drawLabel(QPainter *painter)
{
    if(!get_scale_label_visiable_()){
        return;
    }

    painter->save();

    QRect rect_label = getRotateRectLabel(painter);
    QFontMetrics fm(font());
    QMap<QPointF, QString> map_label_points;
    QPointF left_point, right_point;

    // 根据刻度值绘制
    if(get_scale_type_() == ScaleType_Value){
        // 从左到右
        if(get_scale_direction_() == ScaleDirection_Left_To_Right){
            // 绘制两侧标签
            QString str_min = QString::number(get_scale_range_all_min_(), 'f', 0);
            map_label_points.insert(left_point = QPointF(rect_label.left(), rect_label.bottom()), str_min);
            QString str_max = QString::number(get_scale_range_all_max_(), 'f', 0);
            map_label_points.insert(right_point = QPointF(rect_label.right() - fm.horizontalAdvance(str_max),
                                            rect_label.bottom()), str_max);

            // 绘制标签
            auto label_pix = rect_label.width() / ((get_scale_range_all_max_() - get_scale_range_all_min_()) /
                                                         get_scale_label_value_());
            for(int i = get_scale_range_all_min_() + get_scale_unit_value_();
                i < get_scale_range_all_max_(); i += get_scale_unit_value_()){
                if(i % QString::number(get_scale_label_value_()).toInt()){
                    continue;
                }

                auto index = (i - get_scale_range_all_min_()) / get_scale_label_value_();
                QString str_i = QString::number(i, 'f', 0);
                map_label_points.insert(QPointF(rect_label.left() + index * label_pix - fm.horizontalAdvance(str_i) / 2,
                                                rect_label.bottom()), str_i);
            }
        }
        // 从右到左
        else {
            // 绘制两侧标签
            QString str_max = QString::number(get_scale_range_all_max_(), 'f', 0);
            map_label_points.insert(left_point = QPointF(rect_label.left(), rect_label.bottom()), str_max);
            QString str_min = QString::number(get_scale_range_all_min_(), 'f', 0);
            map_label_points.insert(right_point = QPointF(rect_label.right() - fm.horizontalAdvance(str_min),
                                            rect_label.bottom()), str_min);

            // 绘制标签
            auto label_pix = rect_label.width() / ((get_scale_range_all_max_() - get_scale_range_all_min_()) /
                                                         get_scale_label_value_());
            for(int i = get_scale_range_all_min_() + get_scale_unit_value_();
                i < get_scale_range_all_max_(); i += get_scale_unit_value_()){
                if(i % QString::number(get_scale_label_value_()).toInt()){
                    continue;
                }

                auto index = (i - get_scale_range_all_min_()) / get_scale_label_value_();
                QString str_i = QString::number(i, 'f', 0);
                map_label_points.insert(QPointF(rect_label.right() - index * label_pix - fm.horizontalAdvance(str_i) / 2,
                                                rect_label.bottom()), str_i);
            }
        }
    }
    // 根据刻度个数绘制
    else {
        // 从左到右
        if(get_scale_direction_() == ScaleDirection_Left_To_Right){
            // 绘制两侧标签
            QString str_min = QString::number(get_scale_range_all_min_(), 'f', 0);
            map_label_points.insert(left_point = QPointF(rect_label.left(), rect_label.bottom()), str_min);
            QString str_max = QString::number(get_scale_range_all_max_(), 'f', 0);
            map_label_points.insert(right_point = QPointF(rect_label.right() - fm.horizontalAdvance(str_max),
                                            rect_label.bottom()), str_max);

            // 绘制标签
            auto label_pix = rect_label.width() / (get_scale_label_value_() + 1);
            auto label_value_unit = (get_scale_range_all_max_() - get_scale_range_all_min_()) / (get_scale_label_value_() + 1);
            for(int i = 1; i <= get_scale_label_value_(); i++){
                QString str_i = QString::number(i * label_value_unit + get_scale_range_all_min_(), 'f', 0);
                map_label_points.insert(QPointF(rect_label.left() + i * label_pix -
                                                fm.horizontalAdvance(str_i) / 2,
                                            rect_label.bottom()), str_i);
            }
        }
        // 从右到左
        else {
            // 绘制两侧标签
            QString str_max = QString::number(get_scale_range_all_max_(), 'f', 0);
            map_label_points.insert(left_point = QPointF(rect_label.left(), rect_label.bottom()), str_max);
            QString str_min = QString::number(get_scale_range_all_min_(), 'f', 0);
            map_label_points.insert(right_point = QPointF(rect_label.right() - fm.horizontalAdvance(str_min),
                                            rect_label.bottom()), str_min);

            // 绘制标签
            auto label_pix = rect_label.width() / (get_scale_label_value_() + 1);
            auto label_value_unit = (get_scale_range_all_max_() - get_scale_range_all_min_()) / (get_scale_label_value_() + 1);
            for(int i = 1; i <= get_scale_label_value_(); i++){
                QString str_i = QString::number(i * label_value_unit + get_scale_range_all_min_(), 'f', 0);
                map_label_points.insert(QPointF(rect_label.right() - i * label_pix - fm.horizontalAdvance(str_i) / 2,
                                                rect_label.bottom()), str_i);
            }
        }
    }

    painter->restore();

    // 绘制正常方向文字
    painter->save();
    for(auto it = map_label_points.begin(); it != map_label_points.end(); it++){
        auto p = getRotatePoint(translate_point_, it.key(), rotate_angle_);
        if(rotate_angle_ == 180.){
            p = getRotatePoint(translate_point_, it.key() -
                                QPointF(-fm.horizontalAdvance(it.value()), fm.height() / 2),
                                rotate_angle_);
        }
        if(rotate_angle_ == -90.){
            // QPointF::transposed() QT_VERSION >= 0x00050e00 (Qt 5.14.)
            if(it.key() == left_point){
                p = getRotatePoint(QPointF(translate_point_.y(), translate_point_.x()), it.key() +
                                   QPointF(0, - fm.horizontalAdvance(it.value())),
                                   rotate_angle_);
            } else if(it.key() == right_point){
                p = getRotatePoint(QPointF(translate_point_.y(), translate_point_.x()), it.key() +
                                   QPointF(fm.horizontalAdvance(it.value()) - fm.height() / 2.,
                                           -fm.horizontalAdvance(it.value())),
                                   rotate_angle_);
            } else {
                p = getRotatePoint(QPointF(translate_point_.y(), translate_point_.x()), it.key() +
                                   QPointF((fm.horizontalAdvance(it.value()) - fm.height() / 2.) / 2.,
                                           -fm.horizontalAdvance(it.value())),
                                   rotate_angle_);
            }
            if(get_scale_label_position_() == ScaleLabelPosition_Outside){
                // 左对齐
                p.setX(p.x() + fm.horizontalAdvance(it.value()) - fm.height());
            }
        }
        if(rotate_angle_ == 90.){
            // QPointF::transposed() QT_VERSION >= 0x00050e00 (Qt 5.14.)
            if(it.key() == left_point){
                p = getRotatePoint(QPointF(translate_point_.y(), translate_point_.x()), it.key() +
                                   QPointF(fm.height() / 2., 0),
                                   rotate_angle_);
            } else if(it.key() == right_point){
                p = getRotatePoint(QPointF(translate_point_.y(), translate_point_.x()), it.key() +
                                   QPointF(fm.horizontalAdvance(it.value()), 0),
                                   rotate_angle_);
            } else {
                p = getRotatePoint(QPointF(translate_point_.y(), translate_point_.x()), it.key() +
                                   QPointF((fm.horizontalAdvance(it.value()) + fm.height() / 2.) / 2.,
                                           0),
                                   rotate_angle_);
            }
            if(get_scale_label_position_() == ScaleLabelPosition_Outside){
                // 右对齐
                p.setX(p.x() - fm.horizontalAdvance(it.value()) + fm.height());
            }
        }
        painter->drawText(p, it.value());
    }
    painter->restore();
}

void QLsRuler::drawLine(QPainter *painter)
{
    if(get_ruler_type_() != RulerType_Line){
        return;
    }

    painter->save();
    painter->setPen(Qt::NoPen);

    QRect rect_all = getRotateRectAll(painter);

    // 从左到右
    if(get_scale_direction_() == ScaleDirection_Left_To_Right){
        // 绘制进度线条
        painter->setBrush(get_scale_range_valid_bgcolor_());
        painter->drawRect(
                    rect_all.left() + rect_all.width() *
                    (get_scale_value_() - get_scale_range_all_min_()) /
                    (get_scale_range_all_max_() - get_scale_range_all_min_()) -
                    (get_scale_label_size_().width() + 2) / 2,
                    0,
                    get_scale_label_size_().width() + 2,
                    rect_all.height()
                    );
    }
    // 从右到左
    else {
        // 绘制进度线条
        painter->setBrush(get_scale_range_valid_bgcolor_());
        painter->drawRect(
                    rect_all.left() + rect_all.width() *
                    (get_scale_range_all_max_() - get_scale_value_()) /
                    (get_scale_range_all_max_() - get_scale_range_all_min_()),
                    0,
                    get_scale_label_size_().width() + 2,
                    rect_all.height()
                    );
    }

    painter->restore();
}

void QLsRuler::drawCursor(QPainter *painter)
{
    // 游标标尺和滑动标尺都有游标
    if(!cursor_visiable_){
        return;
    }

    painter->save();
    painter->setPen(Qt::NoPen);

    QRect rect_scale = getRotateRectScale(painter);

    if(get_scale_label_position_() == ScaleLabelPosition_Outside){
        QPointF p;

        // 从左到右
        if(get_scale_direction_() == ScaleDirection_Left_To_Right){
            // 绘制游标
            p.setX(rect_scale.left() + rect_scale.width() *
                   (get_scale_value_() - get_scale_range_all_min_()) /
                   (get_scale_range_all_max_() - get_scale_range_all_min_()));
            p.setY(rect_scale.top() + get_scale_label_size_().height());
        }
        // 从右到左
        else {
            // 绘制游标
            p.setX(rect_scale.left() + rect_scale.width() *
                   (get_scale_range_all_max_() - get_scale_value_()) /
                   (get_scale_range_all_max_() - get_scale_range_all_min_()));
            p.setY(rect_scale.top() + get_scale_label_size_().height());
        }

        triangle_[0] = QPointF(p.x(), p.y() - sqrt(3) * get_cursor_side_() / 4);
        triangle_[1] = QPointF(p.x() - get_cursor_side_() / 2, p.y() + sqrt(3) * get_cursor_side_() / 4);
        triangle_[2] = QPointF(p.x() + get_cursor_side_() / 2, p.y() + sqrt(3) * get_cursor_side_() / 4);
        painter->setBrush(get_cursor_color_());
        painter->drawPolygon(triangle_);
    } else {
        QPointF p;

        // 从左到右
        if(get_scale_direction_() == ScaleDirection_Left_To_Right){
            // 绘制游标
            p.setX(rect_scale.left() + rect_scale.width() *
                   (get_scale_value_() - get_scale_range_all_min_()) /
                   (get_scale_range_all_max_() - get_scale_range_all_min_()));
            p.setY(rect_scale.top() - sqrt(3) * get_cursor_side_() / 4);
        }
        // 从右到左
        else {
            // 绘制游标
            p.setX(rect_scale.left() + rect_scale.width() *
                   (get_scale_range_all_max_() - get_scale_value_()) /
                   (get_scale_range_all_max_() - get_scale_range_all_min_()));
            p.setY(rect_scale.top() - sqrt(3) * get_cursor_side_() / 4);
        }

        triangle_[0] = QPointF(p.x(), p.y() + sqrt(3) * get_cursor_side_() / 4);
        triangle_[1] = QPointF(p.x() - get_cursor_side_() / 2, p.y() - sqrt(3) * get_cursor_side_() / 4);
        triangle_[2] = QPointF(p.x() + get_cursor_side_() / 2, p.y() - sqrt(3) * get_cursor_side_() / 4);
        painter->setBrush(get_cursor_color_());
        painter->drawPolygon(triangle_);
    }

    painter->restore();
}

QRect QLsRuler::getRotateRectAll(QPainter *painter)
{
    QRect rect_all = rect().adjusted(get_padding_left_(), get_padding_top_(), -get_padding_right_(), -get_padding_bottom_());

    switch (get_ruler_direction_()) {
    case RulerDirection_West:       // 上北
        translate_point_ = QPointF(0, 0);
        rotate_angle_ = 0;
        break;
    case RulerDirection_North:{     // 右东
        painter->translate(width(), 0);
        painter->rotate(90);
        auto w = rect_all.width();
        rect_all.setWidth(rect_all.height());
        rect_all.setHeight(w);
        translate_point_ = QPointF(width(), 0);
        rotate_angle_ = 90;
        break;
    }
    case RulerDirection_South:      // 下南
        painter->translate(width(), height());
        painter->rotate(180);
        translate_point_ = QPointF(width(), height());
        rotate_angle_ = 180;
        break;
    case RulerDirection_East:{       // 左西
        painter->translate(0, height());
        painter->rotate(-90);
        auto w = rect_all.width();
        rect_all.setWidth(rect_all.height());
        rect_all.setHeight(w);
        translate_point_ = QPointF(0, height());
        rotate_angle_ = -90;
        break;
    }
    default: break;
    }

    return rect_all;
}

QRect QLsRuler::getRotateRectTrue(QPainter *painter)
{
    QRect rect_all = getRotateRectAll(painter);
    QFontMetrics fm(font());

    // 获取刻度条区域 默认刻度条区域居中
    auto h = (!get_scale_label_visiable_() ? 0 : fm.height() + get_scale_label_space_()) +
            get_scale_label_size_().height() + get_scale_thickness_();
    return QRect(rect_all.left(), rect_all.top() + (rect_all.height() - h) / 2,
                 rect_all.width(), h);
}

QRect QLsRuler::getRotateRectScale(QPainter *painter)
{
    QRect rect_true = getRotateRectTrue(painter);
    QFontMetrics fm(font());

    QRect rect_scale;
    if(scale_label_position_ == ScaleLabelPosition_Inside){
        rect_scale = rect_true.adjusted(
                    0, (!get_scale_label_visiable_()
                        ? 0 : fm.height() + get_scale_label_space_()),
                    0, 0);
    } else {
        rect_scale = rect_true.adjusted(
                    0, 0, 0,
                    -((!get_scale_label_visiable_()
                       ? 0 : fm.height() + get_scale_label_space_())));
    }

    return rect_scale;
}

QRect QLsRuler::getRotateRectLabel(QPainter *painter)
{
    QRect rect_true = getRotateRectTrue(painter);

    QRect rect_label;
    if(scale_label_position_ == ScaleLabelPosition_Inside){
        rect_label = rect_true.adjusted(0, 0, 0, -(get_scale_label_space_() + get_scale_label_size_().height() +
                                                   get_scale_thickness_()));
    } else {
        rect_label = rect_true.adjusted(0, get_scale_label_space_() + get_scale_label_size_().height() +
                                        get_scale_thickness_(), 0, 0);
    }

    return rect_label;
}

QPointF QLsRuler::getRotatePoint(const QPointF &p0, const QPointF &p1, double a)
{
    auto p = p0 - p1;
    p.setX(qFabs(p.x()));
    p.setY(qFabs(p.y()));

    if(qFabs(a) == 90){
        // QPointF::transposed() QT_VERSION >= 0x00050e00 (Qt 5.14.)
        return QPointF(p.y(), p.x());
    }
    return p;
}

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Qt自定义控件大全Designer源码是一个包含了多种自定义控件的全套源码,它主要用于在Qt设计师中使用。Qt是一个跨平台的C++应用程序开发框架,提供了丰富的图形界面控件,但有时候我们可能需要自定义一些特殊的控件来满足我们的需求。 Qt自定义控件大全Designer源码包含了很多常用的自定义控件,如自定义按钮、进度条、滑块、验证码输入框等等。这些控件的设计和实现已经封装好,我们只需要将源码添加到我们的项目中,然后在Qt设计师中直接使用即可。 使用Qt自定义控件大全Designer源码有以下几个优点: 1.提供了丰富的自定义控件选择:Qt自定义控件大全Designer源码包含了多样化的控件,可以满足不同项目的需求。无论是一些简单的控件,还是一些复杂的控件,我们都可以找到合适的选择。 2.减少开发时间和工作量:使用源码中的自定义控件可以减少我们从头开始设计和实现的工作,节省了大量的开发时间和工作量。我们只需要将源码添加到项目中并正确配置,就可以直接在设计师中使用这些自定义控件。 3.提高应用程序的美观性和用户体验:Qt自定义控件大全Designer源码中的控件经过精心设计和实现,具有良好的界面效果和用户交互体验。使用这些自定义控件可以为我们的应用程序提供更加美观和友好的界面。 总之,Qt自定义控件大全Designer源码是一个提供了多种自定义控件的全套源码,使用它可以快速、方便地实现各种自定义控件,提高应用程序的开发效率和用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值