一、应用案例

二、样式展示


注:录制界面为测试界面,实际标尺样式为上半部分

三、源码

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_OBJECTQ_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_, double)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;
}

Qt 自定义控件 标尺控件 QLsRuler相关推荐

  1. QT自定义Widget控件及其使用

    今天来给大家分享一下QT自定义widget控件及其使用,当ui设计器提供的界面不满足实际需求时,可以从QWidget继承自定义的界面组件.有两种方法一种是提升法,另一种是ui设计器自定义界面组件wid ...

  2. qt 容器组控件 Containers

    qt 容器组控件 Containers 控件名: Group Box:组合框,提供带有标题的组合框框架 Scroll Area:滚动区域 Tool Box:工具箱 Tab Widget:标签小部件 S ...

  3. QT中树控件QTreeView开发实例

    转自:http://mobile.51cto.com/symbian-268700.htm 本文讲解了QT中树控件QTreeView开发实例,对于QTreeView没有过多的讲解,那么不说废话了,看代 ...

  4. QT旋转按钮控件的实现

    目录 一.实现需求:鼠标hover时旋转 二.实现方式:计时器做动画 三.代码实现 QT旋转按钮控件的实现 一.实现需求:鼠标hover时旋转 需求是:实现类似于WINDOWS下,某些软件窗口关闭按钮 ...

  5. Qt Creator 窗体控件自适应窗口大小布局

    常见的软件窗口大小改变(最大化.手动改变时)需要窗口的部件能够自适应布局,而在Qt的应用程序界面设计中,对于像我一样的初学者如何实现窗口自适应调整还是要绕点弯路的.网上百度了很多,多数说的很含糊,还有 ...

  6. Qt QTableWidget表格控件的用法(非常详细)

    Qt QTableWidget表格控件的用法(非常详细) QTableWidget 是 Qt 提供的一种表格控件(如图 1 所示),类似于我们经常使用的 Excel 表格,可以将数据以表格的方式展示给 ...

  7. Qt 之 ActiveX控件跑官方例程记录

    转载自:Qt 之 ActiveX控件跑官方例程记录 通过自己的实践,补充了一些技术细节 目录(?)[-] 开发环境 基础知识了解 QT的ActiveX控件形式 in-process运行的ActiveX ...

  8. Qt第三方图形控件qwt的编译安装与使用的简单方法(Win7+Qt4.8.6+MinGW4.8.2)

    一.前言 qwt虽然强大,但是安装和编译还是有些费劲的,网上资料各种奇怪的安装方法都有,但经过博主多方尝试,终于还是发现,根据qwt官方安装文档安装才是最简单省力的.步骤很简单,下面分别介绍. 二.下 ...

  9. QT 自定义分页控件

    Qt 自定义页码控件 一.效果展示 二.头文件 #ifndef PAGECONTROL_H #define PAGECONTROL_H #include <QList> #include ...

最新文章

  1. 宏基因组扩增子1图表解读-理解文章思路,零基础测序分析图表解读大全(箱线,散点,热,曼哈顿,火山,韦恩,三元,网络),老板再也不愁我的文献阅读了!
  2. iOS App 上架(Analysis 工具使用)
  3. mac 上安装服务,查看服务,重启和关闭
  4. 【Matlab】一个超简单的生成顺序数组的方法
  5. error LNK2005: _DllMain@12 already defined的解决办法
  6. python3解释器执行'abcdd'.endswith('cd')的结果是___python3解释器执行for x
  7. Ubicomp一些有意思的论文
  8. Python----倚楼听风雨
  9. android 开发工具类,Android中常用开发工具类—持续更新...
  10. python--之Python内存监控模块memory_profiler测试
  11. java基础之继承(一)
  12. 解决滑动UITableView自动显示delete按钮
  13. iOS 11.2 - 11.3.1 越狱教程
  14. mc9.1编程教程入门_教程1-什么是编程?
  15. →箭头符号大全复制_WORD特殊符号大全lpar;直接复制即可rpar;
  16. java 线程 假死_JVM假死问题如何定位?
  17. OneNote for win10 无法加载笔记本
  18. python+opencv填充图像不规则区域:fillPoly和fillConvexPoly区别、半透明填充方法
  19. pybullet机器人运动质心轨迹/足端轨迹显示adduserdebugline
  20. C/C++百题打卡[5/100]——合唱队形

热门文章

  1. 中移物联ML302开发板上手体验
  2. python的转义字符,以及字符串输出转义字符
  3. 【nlp学习】中文命名实体识别(待补充)
  4. # 学号12 2016-2017-2 《程序设计与数据结构》第9周学习总结
  5. #贴改色膜前,你必须要知道的事情
  6. 当代年轻人该如何跨越阶层?
  7. 学好MySQL增删查改,争取不做CURD程序员【上篇】
  8. python金融风控评分卡模型和数据分析
  9. Python生成器next方法和send方法区别详解
  10. WiFi工作原理简述