Qt(C++)绘制指针仪表盘显示当前温度

举报
DS小龙哥 发表于 2023/06/27 09:06:21 2023/06/27
【摘要】 使用Qt绘制一个仪表盘,用来显示当前的温度,绘制刻度、绘制数字、绘制温度指针。仪表盘全程使用QPainter进行绘制,QPainter是Qt框架中非常重要的一个类,绘制功能的实现离不开它。如果想要使用Qt进行高质量的绘图或UI设计,必须掌握QPainter的使用方法。

一、功能介绍

当前文章要实现的功能:

使用Qt绘制一个仪表盘,用来显示当前的温度,绘制刻度、绘制数字、绘制温度指针。仪表盘全程使用QPainter进行绘制,QPainter是Qt框架中非常重要的一个类,绘制功能的实现离不开它。如果想要使用Qt进行高质量的绘图或UI设计,必须掌握QPainter的使用方法。

QPainter的简介:

QPainter是Qt里用于绘制图形的类,提供了各种绘制函数,可以绘制几何图形、文本、图片等等。QPainter所绘制的图形可以在QWidget及其子类的paintEvent()事件中使用,也可以在QPixmap等其他对象中进行绘制。

QPainter的大致使用流程如下:

 1. 创建一个QPainter对象,需要传入一个绘制设备,例如QWidget或QPixmap。
 2. 用QPainter的各种绘制函数来绘制几何图形、文本、图片等等。
 3. 在绘制完成后,将画笔和画刷等状态还原到初始状态。
 4. 在必要时释放QPainter对象。

温度仪表盘最终绘制出的效果--带数字刻度:

image-20230530163418909

image-20230530164040271

无数字刻度效果:

image-20230530161040237

二、代码设计过程

【1】定义一个自定义控件my_DrawDashboard,继承QWidget类

 class my_DrawDashboard : public QWidget
 {
     Q_OBJECT
 ​
 public:
     explicit my_DrawDashboard(QWidget *parent = nullptr);
     ~my_DrawDashboard();
 ​
 protected:
     void paintEvent(QPaintEvent *event) override;
 ​
 private:
     int m_temperature;
 ​
 signals:
     void temperatureChanged(int temperature);
 ​
 public slots:
     void setTemperature(int temperature);
 };

【2】在my_DrawDashboard的构造函数中初始化温度及其他属性值

 MyWidget::MyWidget(QWidget *parent)
     : QWidget(parent)
 {
     m_temperature = 0;
     setMinimumSize(200, 200);
     setMaximumSize(200, 200);
 }

【3】在my_DrawDashboard中实现paintEvent()函数,绘制仪表盘

 void my_DrawDashboard::paintEvent(QPaintEvent *event)
 {
     Q_UNUSED(event)
 ​
     // 定义画布和画笔
     QPainter painter(this);
     painter.setRenderHint(QPainter::Antialiasing);
     int w = width();
     int h = height();
     int radius = qMin(w, h) / 2;
     QPoint center(w / 2, h / 2);
     QFont font("Arial", radius * 0.1, QFont::Bold);
     painter.setFont(font);
 ​
     // 绘制背景圆
     painter.setPen(Qt::NoPen);
     painter.setBrush(QColor("#EEEEEE"));
     painter.drawEllipse(center, radius, radius);
 ​
     // 绘制刻度
     painter.setPen(QPen(Qt::black, radius * 0.02));
     for (int i = 0; i <= 10; ++i) {
         int angle = i * 30;
         painter.drawLine(center + QPoint(radius * cos(angle * M_PI / 180.0), radius * sin(angle * M_PI / 180.0)),
                          center + QPoint((radius - radius * 0.15) * cos(angle * M_PI / 180.0),
                                          (radius - radius * 0.15) * sin(angle * M_PI / 180.0)));
     }
 ​
     // 绘制温度指针
     painter.setPen(QPen(Qt::red, radius * 0.05));
     painter.setBrush(Qt::red);
     painter.save();
     int angle = -135 + m_temperature * 27 / 5;
     painter.rotate(angle);
     QPointF pointer[3] = { center + QPoint(radius * 0.05, 0),
                            center + QPoint(-radius * 0.05, 0),
                            center + QPoint(0, -radius * 0.9) };
     painter.drawConvexPolygon(pointer, 3);
     painter.restore();
 ​
     // 绘制当前温度值
     painter.setPen(Qt::black);
     painter.drawText(QRectF(center.x() - radius * 0.5, center.y() + radius * 0.2, radius, radius), Qt::AlignCenter,
                      QString("%1℃").arg(m_temperature));
 }

【4】在my_DrawDashboard中提供一个setTemperature()函数,用于更新当前温度并触发temperatureChanged信号

 void my_DrawDashboard::setTemperature(int temperature)
 {
     if (m_temperature == temperature)
         return;
 ​
     m_temperature = temperature;
     update();
     emit temperatureChanged(m_temperature);
 }

【5】使用QTimer来模拟温度的变化,并实时更新仪表盘的显示

 // 在主窗口中创建my_DrawDashboard控件
 my_DrawDashboard *widget = new my_DrawDashboard(this);
 ​
 // 创建QTimer对象并绑定温度变化槽函数
 QTimer *timer = new QTimer(this);
 connect(timer, &QTimer::timeout, this, [&widget](){
     int temperature = qrand() % 31 - 10;
     widget->setTemperature(temperature);
 });
 ​
 // 启动定时器
 timer->start(1000);

上面代码中,在主窗口中创建了一个my_DrawDashboard控件,使用QTimer对象来模拟温度的变化。每隔1秒钟生成一个随机的温度值,调用my_DrawDashboard的setTemperature()函数来更新当前温度,并实时更新仪表盘的显示。

三、完整的工程

【1】my_DrawDashboard.cpp

 #include "my_drawdashboard.h"
 ​
 my_DrawDashboard::my_DrawDashboard(QWidget *parent)
     : QWidget(parent)
 {
     m_temperature = 0;
     //setMinimumSize(100, 100);
    // setMaximumSize(100, 100);
 }
 ​
 ​
 ​
 void my_DrawDashboard::paintEvent(QPaintEvent *event)
 {
     Q_UNUSED(event)
 ​
     // 定义画布和画笔
     QPainter painter(this);
     painter.setRenderHint(QPainter::Antialiasing);
     int w = width();
     int h = height();
     int radius = qMin(w, h) / 2;
     QPoint center(w / 2, h / 2);
     QFont font("Arial", radius * 0.1, QFont::Bold);
     painter.setFont(font);
 ​
     // 绘制背景圆
     painter.setPen(Qt::NoPen);
     painter.setBrush(QColor("#EEEEEE"));
     painter.drawEllipse(center, radius, radius);
 ​
     // 绘制刻度
     painter.setPen(QPen(Qt::black, radius * 0.02));
     for (int i = 0; i <= 10; ++i) {
         int angle = i * 30;
         painter.drawLine(center + QPoint(radius * cos(angle * M_PI / 180.0), radius * sin(angle * M_PI / 180.0)),
                          center + QPoint((radius - radius * 0.15) * cos(angle * M_PI / 180.0),
                                          (radius - radius * 0.15) * sin(angle * M_PI / 180.0)));
     }
 ​
     // 绘制温度指针
     painter.setPen(QPen(Qt::red, radius * 0.05));
     painter.setBrush(Qt::red);
     painter.save();
     int angle = -135 + m_temperature * 27 / 5;
 ​
     //painter.rotate(60);
     QPointF pointer[3] = { center + QPoint(radius * 0.05, 0),
                            center + QPoint(-radius * 0.05, 0),
                            center + QPoint(0, -radius * 0.9) };
     painter.drawConvexPolygon(pointer, 3);
     painter.restore();
 ​
     // 绘制当前温度值
     painter.setPen(Qt::black);
     painter.drawText(QRectF(center.x() - radius * 0.5, center.y() + radius * 0.2, radius, radius), Qt::AlignCenter,
                      QString("%1℃").arg(m_temperature));
 }
 ​
 ​
 void my_DrawDashboard::setTemperature(int temperature)
 {
     if (m_temperature == temperature)
         return;
 ​
     m_temperature = temperature;
     update();
     emit temperatureChanged(m_temperature);
 }

【2】my_DrawDashboard.h

 #ifndef MY_DRAWDASHBOARD_H
 #define MY_DRAWDASHBOARD_H
 ​
 #include <QWidget>
 #include <QPainter>
 #include <qmath.h>
 ​
 class my_DrawDashboard : public QWidget
 {
     Q_OBJECT
 ​
 public:
     explicit my_DrawDashboard(QWidget *parent = nullptr);
     //~my_DrawDashboard();
 protected:
     void paintEvent(QPaintEvent *event) override;
 ​
 private:
     int m_temperature=20;
 ​
 signals:
     void temperatureChanged(int temperature);
 ​
 public slots:
     void setTemperature(int temperature);
 };
 ​
 ​
 #endif // MY_DRAWDASHBOARD_H

【3】设计UI界面

在主窗口上,拖拽一个QWidget控件,提升为my_DrawDashboard类型。

image-20230530161716856

image-20230530161843349

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。