Qt绘制仪表————附带详细说明和代码示例

文章目录

  • 1 效果
  • 2 原理
  • 3 编码实践
    • 3.1 创建仪表属性类
    • 3.2 设置类属性
    • 3.3 绘制图案
      • 3.3.1 设置反走样
      • 3.3.2 绘制背景
      • 3.3.3 重新定义坐标原点
      • 3.3.4 绘制圆环
      • 3.3.5 绘制刻度线
      • 3.3.6 绘制刻度线上的描述值
      • 3.3.7 绘制指针
      • 3.3.8 绘制指针数值和单位
      • 3.3.9 控制指针变化
  • 扩展
  • 福利
  • 参考

1 效果

下面仪表模拟的是转速表和速度表,转速表中有怠速转速,降功转速的逻辑。
在这里插入图片描述
下面是模拟双针仪表的效果:

在这里插入图片描述

2 原理

1,重写paintEvent进行仪表绘制,使用QPropertyAnimation进行动画绘制;

2,进行属性动画绘制时,需要使用Q_PROPERTY宏用于声明类的属性;

3 编码实践

下面代码位调用方法,接口的具体实现在后文中有详细描述。

发射的信号:

    //发送发动机转速
    void sendEngineSpeed(double);

    //发送大机速度值
    void sendTrainSpeedNum(short);

创建仪表类并设置参数:


    //发动机转速表
    DashBoardWidget3 *dashBoardWidget5 = new DashBoardWidget3(this);
    dashBoardWidget5->setScaleMajor(6);//6个大区间
    dashBoardWidget5->setScaleMinor(5);//每个区间5个小格
    dashBoardWidget5->setUnit("");
    dashBoardWidget5->setText("RPMx100");
    dashBoardWidget5->setmax(30);
    dashBoardWidget5->setUnitDrawInterval(1);//每隔一个大区间画一个刻度线描述值
    dashBoardWidget5->setGeometry(750, 20, 300, 300);

    connect(this, &MainInterface::sendEngineSpeed,
            dashBoardWidget5, &DashBoardWidget3::valueChanged);

    //汽车速度表
    DashBoardWidget3 *dashBoardWidget6 = new DashBoardWidget3(this);
    dashBoardWidget6->setScaleMajor(12);//大区间
    dashBoardWidget6->setScaleMinor(2);//每个区间的小值
    dashBoardWidget6->setUnit("");
    dashBoardWidget6->setText("km/h");
    dashBoardWidget6->setmax(120);
    dashBoardWidget6->setUnitDrawInterval(2);
    // dashBoardWidget->move(600, 20);
    dashBoardWidget6->setGeometry(750, 300, 300, 300);

    connect(this, &MainInterface::sendTrainSpeedNum,
            dashBoardWidget6, &DashBoardWidget3::valueChanged);

3.1 创建仪表属性类

struct DashBoardWidgetPrivate{
    //刻度值的最大值和最小值
    int maxValue = 100;
    int minValue = 0;

    //刻度值角度
    double startAngle = -50;
    double endAngle = 230;
    double value = minValue;

    //大区间,最小区间
    int scaleMajor = 10;
    int scaleMinor = 5;

    //单位和描述文字
    QString unit = "";
    QString text = "";

    //仪表颜色
    QColor arcColor = QColor(56, 61, 74);//QColor(0, 128, 255);
    //刻度颜色
    QColor scaleColor = QColor(71, 186, 252);//QColor(4, 168, 173);
    //指针颜色
    QColor pointerColor = QColor(255, 0, 0);
    //文件颜色
    QColor textColor = QColor(144, 133, 116);
    //背景颜色
    QColor backgroundColor = Qt::transparent;

    //仪表指针1:属性动画
    QPropertyAnimation *animation;

};

3.2 设置类属性

    Q_PROPERTY(double value READ value WRITE setValue)
    Q_PROPERTY(double min READ min WRITE setMin)
    Q_PROPERTY(double max READ max WRITE setmax)
    Q_PROPERTY(double startAngle READ startAngle WRITE setStartAngle)
    Q_PROPERTY(double endAngle READ endAngle WRITE setEndAngle)
    Q_PROPERTY(int scaleMajor READ scaleMajor WRITE setScaleMajor)
    Q_PROPERTY(int scaleMinor READ scaleMinor WRITE setScaleMinor)
    Q_PROPERTY(QString unit READ unit WRITE setUnit)
    Q_PROPERTY(QString text READ text WRITE setText)
    Q_PROPERTY(QColor arcColor READ arcColor WRITE setArcColor)
    Q_PROPERTY(QColor scaleColor READ scaleColor WRITE setScaleColor)
    Q_PROPERTY(QColor pointerColor READ pointerColor WRITE setPointerColor)
    Q_PROPERTY(QColor textColor READ textColor WRITE setTextColor)
    Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)

创建对应的函数:

    QSize sizeHint() const override;
    QSize minimumSizeHint() const override;

    double value() const;
    void setValue(const double value);

    void setMin(const double min);
    double min() const;

    void setmax(const double max);
    double max() const;

    void setStartAngle(const double startAngle);
    double startAngle() const;

    void setEndAngle(const double endAngle);
    double endAngle() const;

    void setScaleMajor(const int scale);
    int scaleMajor() const;

    void setScaleMinor(const int scale);
    int scaleMinor() const;

    void setUnit(const QString &unit);//设置单位
    QString unit() const;

    void setText(const QString &text);//设置文字
    QString text() const;

    void setArcColor(const QColor &color);
    QColor arcColor() const;

    void setScaleColor(const QColor &color);
    QColor scaleColor() const;

    void setPointerColor(const QColor &color);
    QColor pointerColor() const;

    void setTextColor(const QColor &color);
    QColor textColor() const;

    void setBackgroundColor(const QColor &color);
    QColor backgroundColor() const;

3.3 绘制图案

在类绘制事件中,添加各种绘制信息:

void DashBoardWidget3::paintEvent(QPaintEvent *event){
    QWidget::paintEvent(event);
	QPainter painter(this);
    
    //....
}

3.3.1 设置反走样

//反走样是图形学中的重要概念,用以防止通常所说的“锯齿”现象的出现。很多系统的绘图 API 里面都内置了有关反走样的算法,不过由于性能问题,默认一般是关闭的

painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

3.3.2 绘制背景

    // 背景
    if (d->backgroundColor != Qt::transparent) {
        painter.setPen(Qt::NoPen);
        painter.fillRect(rect(), d->backgroundColor);
    }

3.3.3 重新定义坐标原点

    // 平移中心
    painter.translate(width() / 2, height() / 2);

调整之前:
在这里插入图片描述

调整之后:

在这里插入图片描述

3.3.4 绘制圆环

    // 圆环
    drawArc(&painter);

实现函数:

void DashBoardWidget3::drawArc(QPainter *painter)
{
    double min = qMin(width(), height());
    double arcWidth = min / 15.0;
    double radius = min / 3 - arcWidth;
    QRectF rect = QRectF(-radius, -radius, radius * 2, radius * 2);
    QPen pen;
    pen.setWidthF(arcWidth);
    pen.setCapStyle(Qt::FlatCap);

    // 圆弧背景
    double angle = d->endAngle - d->startAngle;
    pen.setColor(d->arcColor);
    painter->setPen(pen);
    painter->drawArc(rect, d->startAngle * 16, angle * 16);
}

绘制效果如下:

在这里插入图片描述

3.3.5 绘制刻度线

    // 刻度线
    drawScale(&painter);

实现函数:

void DashBoardWidget3::drawScale(QPainter *painter)
{
    painter->save();

    painter->rotate(270 - d->endAngle);
    int steps = (d->scaleMajor * d->scaleMinor);//区间*每个区间的小刻度
    double angleStep = (d->endAngle - d->startAngle) / steps;
    double min = qMin(width(), height());
    double radius = min / 3;

    QPen pen(d->scaleColor);
    pen.setCapStyle(Qt::RoundCap);

    for (int i = 0; i <= steps; i++) {
        if (i % d->scaleMinor == 0) {//画大刻度
            pen.setWidthF(1.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 8, 0, radius + 5);//画刻度线长度
        }
        else
        {//画小刻度
            pen.setWidthF(0.5);
            painter->setPen(pen);
            painter->drawLine(0, radius - 8, 0, radius - 3);
        }

        painter->rotate(angleStep);
    }

    painter->restore();
}

效果如下:

在这里插入图片描述

3.3.6 绘制刻度线上的描述值

    // 刻度线上的描述值
    drawScaleNum(&painter);

实现函数:

//画刻度线上的说明值
void DashBoardWidget3::drawScaleNum(QPainter *painter)
{
    painter->save();
    painter->setPen(d->scaleColor);
    double min = qMin(width(), height());
    double radius = min / 2.4;//半径
    QFont font("Microsoft YaHei", min / 25);
    painter->setFont(font);

    double startRad = d->endAngle * (M_PI / 180);
    //qDebug()<<"startRad:"<<startRad;
    double deltaRad = (d->endAngle - d->startAngle) * (M_PI / 180) / d->scaleMajor;

    QFontMetrics fontMetrics(font);

    if(m_unitDrawInterval > d->scaleMajor){
        m_unitDrawInterval = d->scaleMajor;
    }

    for (int i = 0; i <= d->scaleMajor; i += m_unitDrawInterval) {//每个大区间都要画刻度值
        double sina = qSin(startRad - i * deltaRad);
        double cosa = qCos(startRad - i * deltaRad);
        double value = 1.0 * i * ((d->maxValue - d->minValue) / d->scaleMajor) + d->minValue;
        // 1.0 * 1 *((1200 -0)/10) + 0

       // qDebug()<<"d->maxValue:"<<d->maxValue;
        //qDebug()<<"d->minValue:"<<d->minValue;
        //qDebug()<<"value:"<<value;

        QString strValue = QString("%1").arg(value);
        double textWidth = fontMetrics.horizontalAdvance(strValue);
        double textHeight = fontMetrics.height();
        int x = radius * cosa - textWidth / 2;
        int y = -radius * sina + textHeight / 4;
        painter->drawText(x, y, strValue);
    }

    painter->restore();
}

效果如下:

在这里插入图片描述

3.3.7 绘制指针

    // 指示器(指针)
    drawPointer(&painter);

实现函数:

//画指针
void DashBoardWidget3::drawPointer(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(d->pointerColor);//设置画笔颜色

    double radius = qMin(width(), height()) / 3.0;

    QPolygonF pts;
    pts << QPointF(-5, 0) << QPointF(0, -8)
        << QPointF(5, 0) << QPointF(0, radius);

    painter->rotate(270 - d->endAngle);
    double degRotate = (d->endAngle - d->startAngle) / (d->maxValue - d->minValue) * (d->value - d->minValue);
    painter->rotate(degRotate);
    painter->drawConvexPolygon(pts);

    painter->restore();
}

效果如下:

在这里插入图片描述

3.3.8 绘制指针数值和单位

    // 显示指针数值和单位
    drawValue(&painter);

实现函数:

//画数值和单位
void DashBoardWidget3::drawValue(QPainter *painter)
{
    painter->save();
    painter->setPen(d->textColor);

    double min = qMin(width(), height());
    double radius = min / 2.0 - min / 4.8;
    QFont font("Microsoft YaHei", min / 25);
    painter->setFont(font);
    
    //绘制指针数值和单位
    QString strValue = QString("%1 %2").arg(d->value).arg(d->unit);
    QRectF valueRect(-radius, radius / 2.5, radius * 2, radius / 3.5);
    QColor pointerColor = QColor(0, 0, 0);
    painter->setBrush(pointerColor);
    //设置颜色
    painter->setPen(QPen(QColor(0, 0, 0)));
    painter->drawText(valueRect, Qt::AlignCenter, strValue);
    
    
    //绘制描述文字
    QRectF text2Rect(-radius, radius / 1.5, radius * 2, radius / 2.5);
    painter->setPen(QPen(QColor(255, 0, 0)));//设置画笔颜色
    painter->setBrush(d->textColor);//设置画笔颜色
    font.setPixelSize(12);
    painter->setFont(font);
    painter->drawText(text2Rect, Qt::AlignCenter, d->text);

    painter->restore();
}

实现效果:

在这里插入图片描述

3.3.9 控制指针变化

signals:
    void valueChanged(const double value);


DashBoardWidget3::DashBoardWidget3(QWidget *parent)
    : QWidget(parent)
    , d(new DashBoardWidgetPrivate)
{
    d->animation = new QPropertyAnimation(this, "value", this);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    connect(this, &DashBoardWidget3::valueChanged,
            this, &DashBoardWidget3::onStartAnimation);

}

实现函数:

//仪表指针变动的动画
void DashBoardWidget3::onStartAnimation(double value)
{

    if(value < d->minValue
        || value > d->maxValue
        || value == d->value){

    }else{
        double start = d->value;
        double end = value;

        d->animation->setStartValue(start);
        d->animation->setEndValue(end);
        d->animation->start();
    }
}

扩展

可以思考以下,下面的效果如何实现?

在这里插入图片描述

福利

完整的项目代码

欢迎各位start

参考

Qt自定义控件之仪表盘的完整实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/937484.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

音频客观测评方法PESQ

一、简介 语音质量感知评估&#xff08;Perceptual Evaluation of Speech Quality&#xff09;是一系列的标准&#xff0c;包括一种用于自动评估电话系统用户所体验到的语音质量的测试方法。该标准于2001年被确定为ITU-T P.862建议书[1]。PESQ被电话制造商、网络设备供应商和电…

axios请求拦截器和响应拦截器,封装naive-ui的 Loading Bar加载条和useMessage消息提示

接之前的博客设计从0开始边做边学&#xff0c;用vue和python做一个博客&#xff0c;非规范化项目&#xff0c;怎么简单怎么弄&#xff0c;跑的起来有啥毛病解决啥毛病&#xff08;三&#xff09;&#xff0c;目前已经完成了基本的功能demo&#xff0c;但是请求接口不可能每个页…

uniapp的多列选择器

1.代码如下 <template><view class"container"><form><picker mode"multiSelector" :range"multiArray" change"onMultiChange" columnchange"onMultiColumnChange"><view class"picker&q…

C# 探险之旅:第三十三节 - 类型class(静态成员和静态类Static Members 和 Static Classes):一场不“动”声色的冒险

嘿&#xff0c;勇敢的探险家们&#xff01;欢迎再次踏上C#的神秘之旅。今天&#xff0c;我们要探索的是一个神秘而又特别的领域——静态成员和静态类。想象一下&#xff0c;这是一群“懒得动”的家伙&#xff0c;他们不喜欢随着对象的创建而四处奔波&#xff0c;更喜欢安安静静…

国威HB1910数字程控电话交换机 generate.php 未授权RCE漏洞复现

0x01 产品简介 国威HB1910数字程控电话交换机是一款功能强大的通信设备,国威HB1910数字程控电话交换机符合国家工信部YD 344-1990《自动用户交换机进网要求》规范,以及其他多项国家安全标准规范,如YD/T 1141-2007、YD/T 729-1994、YD/T 751-1995等。同时,设备还具备自动检…

信奥赛CSP-J复赛集训(bfs专题)(5):洛谷P3395:路障

信奥赛CSP-J复赛集训(bfs专题-刷题题单及题解)(5):洛谷P3395:路障 题目描述 B 君站在一个 n n n\times n n

CTF-WEB: php-Session 文件利用 [第一届国城杯 n0ob_un4er 赛后学习笔记]

step 1 搭建容器 教程 A5rZ 题目 github.com Dockerfile 有点问题,手动修复一下 FROM php:7.2-apacheCOPY ./flag /root COPY ./readflag / COPY ./html/ /var/www/html/ COPY ./php.ini /usr/local/etc/php/php.ini COPY ./readflag /readsecretRUN chmod 755 /var/www…

【经验分享】搭建本地训练环境知识点及方法

最近忙于备考没关注&#xff0c;有次点进某小黄鱼发现首页出现了我的笔记还被人收费了 虽然我也卖了一些资源&#xff0c;但我以交流、交换为主&#xff0c;笔记都是免费给别人看的 由于当时刚刚接触写的并不成熟&#xff0c;为了避免更多人花没必要的钱&#xff0c;所以决定公…

FastJson反序列化学习-01

&#x1f338; FastJson FastJson是一个由阿里巴巴开发的高性能JSON处理库&#xff0c;支持Java对象与JSON字符串之间的互相转换。 本次漏洞研究基于FastJson的1.2.24版本。也就是最早出现FastJson反序列化漏洞的版本。 CVE-2017-18349&#xff0c;FastJson<1.2.24 &…

【恶意软件检测论文】通过提取 API 语义来实现的一个新颖的安卓恶意软件检测方法

目录 摘要1. 引言2. 相关工作2.1. 基于重新训练的恶意软件检测2.2. 基于应用关系图的恶意软件检测2.3. 基于异常样本识别的恶意软件检测2.4. 基于API聚类的恶意软件检测 3. AMDASE概述4. 基于语义距离的API聚类4.1. API特征提取4.2. API句子生成4.3. API句子编码4.4.聚类中心生…

【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数(四)

目录 ARC规则 规则 对象型变量不能作为C语言结构体的成员 显式转换id和void* 属性 数组 ARC规则 规则 在ARC有效的情况下编译源代码必须遵守一定的规则&#xff1a; 主要解释一下最后两条 对象型变量不能作为C语言结构体的成员 要把对象型变量加入到结构体成员中时&a…

location重定向和nginx代理

文章目录 1 location重定向1.1 概述1.2 rewrite跳转1.3 用例1.4 实验1.4.1 基于域名的跳转1.4.2 基于ip的跳转1.4.3 基于后缀名的跳转 2 nginx的代理2.1 nginx内置变量2.2 正向代理2.2.1 固定正向代理2.2.2 自动代理 2.3 反向代理2.3.1 负载均衡的算法2.3.2 负载均衡的特点2.3.…

【Qt】qt基础

目录 一、使用Qt Creator创建qt项目 二、项目文件解析 三、Qt中创建图形化界面的程序的两种方法 四、对象树 五、Qt中处理打印乱码问题的利器&#xff1a;qDebug() 一、使用Qt Creator创建qt项目 1.选择项目模板 选中第一类模板Application(Qt应用程序&#xff0c;包含普…

CSS在线格式化 - 加菲工具

CSS在线格式化 打开网站 加菲工具 选择“CSS在线格式化” 或者直接访问 https://www.orcc.online/tools/css 输入CSS代码&#xff0c;点击左上角的“格式化”按钮 得到格式化后的结果

java之集合(详细-Map,Set,List)

1集合体系概述 1.1集合的概念 集合是一种容器&#xff0c;用来装数据的&#xff0c;类似于数组&#xff0c;但集合的大小可变&#xff0c;开发中也非常常用。 1.2集合分类 集合分为单列集合和多列集合 Collection代表单列集合&#xff0c;每个元素&#xff08;数据&#xff…

C语言刷题

1. 题目描述 根据给出的三角形3条边a:b.c(a.b,c<100.000)&#xff0c;计算三角形的周长和面积。 输入描述: 一行&#xff0c;三角形3条边(能构成三角形)&#xff0c;中间用一个空格隔开. 输出描述: 一行&#xff0c;三角形周长和面积保留两位小数&#xff0c;中问用一个空…

自动驾驶控制与规划——Project 1: 车辆纵向控制

目录 零、任务介绍一、环境配置1.1 CARLA的配置1.2 Docker Ubuntu 20.04 ROS2 Foxy的配置 二、算法2.1 定速巡航2.2 自适应巡航2.3 离散PID控制 三、代码实现3.1 代码补全3.2仿真验证 零、任务介绍 课程主页 配置Carla仿真器配置carla-ros-bridge补全src\ros-bridge\carla_s…

Linux高并发服务器开发 第一天(Linux的目录结构 cd用法 终端提示符格式)

目录 1.命令解析器&#xff1a;shell 2.LINUX下的目录结构 3.cd的使用 3.1cd 绝对路径 3.2cd 相对路径 3.3cd 回车 3.4cd - 4. 终端提示符格式 1.命令解析器&#xff1a;shell 默认运行与计算机系统终端的 用来解析用户输入命令的工具 内核&#xff1a;操作系统的核…

[SAP ABAP] 序列化与反序列化

1.序列化 序列化表示将ABAP对象类型转成json字符串 我们可以使用方法/ui2/cl_json>serialize实现序列化&#xff0c;可以将ABAP中的内表结构转成json字符串类型 REPORT z437_test_2024.* 自定义数据类型 TYPES: BEGIN OF ty_makt,matnr LIKE makt-matnr, " 物料编号…

【h5py】 提取mat文件中的HDF5格式的数据

h5py 提取mat文件中的HDF5格式的数据 使用纯Python查看数据配合Matlab后&#xff0c;使用Python查看数据 一、使用纯Python查看文件数据内容 原理&#xff1a;当HDF5存储的是struct类型数据&#xff0c;解析时要像一棵树&#xff0c;我们需要逐层次的去解析&#xff0c;直到…