一、功用介绍

当时文章要完成的功用:

运用Qt制作一个仪表盘,用来显现当时的温度,制作刻度、制作数字、制作温度指针。仪表盘全程运用QPainter进行制作,QPainter是Qt框架中非常重要的一个类,制作功用的完成离不开它。假如想要运用Qt进行高质量的绘图或UI规划,必须把握QPainter的运用方法。

QPainter的简介:

QPainter是Qt里用于制作图形的类,供给了各种制作函数,能够制作几何图形、文本、图片等等。QPainter所制作的图形能够在QWidget及其子类的paintEvent()事情中运用,也能够在QPixmap等其他目标中进行制作。

QPainter的大致运用流程如下:

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

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

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

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

无数字刻度效果:

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

二、代码规划过程

【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类型。

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

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