大家好,今天主要和大家聊一聊,如何使用QT进行绘图和图标的方法。
第一:绘图和图表简介
绘图与图表在嵌入式里有的比较多,尤其是图表,我们常在股票里看到的“图表折线/曲线图/饼状图等”都可以用 Qt 的图表来实现。绘图和图表的内容本章主要介绍绘图和图表的基本操作,以简单的例子呈现绘图与图表的用法,目的就是快速入门绘图与图表
QT里面所有的绘图,比如一个按钮和一个Label的显示,都有绘图系统来执行。绘图系统基于QPainter和QPaintDevice类。QPainter 是可以直接用来操作绘图的类,而 QPaintDevice 和 QPainEngine 都比 QPainter 更底层,我们只需要了解一下 QPaintDevice 和 QPainEngine 就行了。可以用下面一张图来表示它们的关系。
第二:绘图应用实例
本次使用一张CD图片,用QPainter在paintEvent()将 CD 画在窗口的中心,并且每 100ms 旋转 1 度角度。所以 CD 看起来是旋转了的效果。
//在头文件“mainwindow.h”的具体代码实现如下
1 #ifndef MAINWINDOW_H
2 #define MAINWINDOW_H
3
4 #include <QMainWindow>
5 #include <QPainter>
6 #include <QPaintEvent>
7 #include <QTimer>
8
9 class MainWindow : public QMainWindow
10 {
11 Q_OBJECT
12
13 public:
14 MainWindow(QWidget *parent = nullptr);
15 ~MainWindow();
16
17 /* 重写父类下的 protected 方法*/
18 protected:
19 void paintEvent(QPaintEvent *);
20
21 private:
22 /* 定时器,用于定时更新界面 */
23 QTimer *timer;
24 /* 角度 */
25 int angle;
26
27 private slots:
28 /* 槽函数 */
29 void timerTimeOut();
30
31 };
32 #endif // MAINWINDOW_H
第 18 行,因为 paintEvent()是父类 QWidget 的 protected 修饰符下虚方法(虚函数),所以建议重写时也写到子类下的 protected 修饰符下。
第三:源文件mainwindow.cpp的具体实现
1 #include "mainwindow.h"
2 #include "QDebug"
3 MainWindow::MainWindow(QWidget *parent)
4 : QMainWindow(parent)
5 {
6 /* 设置主窗口位置及颜色 */
7 this->setGeometry(0, 0, 800, 480);
8 setPalette(QPalette(Qt::gray));
9 setAutoFillBackground(true);
10
11 /* 定时器实例化 */
12 timer = new QTimer(this);
13
14 /* 默认角度为 0 */
15 angle = 0;
16
17 /* 定时 100ms */
18 timer->start(100);
19
20 /* 信号槽连接 */
21 connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeOut()));
22 }
23
24 MainWindow::~MainWindow()
25 {
26 }
27
28 void MainWindow::timerTimeOut()
29 {
30 /* 需要更新界面,不设置不更新 */
31 this->update();
32 }34 void MainWindow::paintEvent(QPaintEvent *)
35 {
36 /* 指定父对象,this 指本窗口 */
37 QPainter painter(this);
38
39 /* 设置抗锯齿,流畅转换 */
40 painter.setRenderHints(QPainter::Antialiasing
41 | QPainter::SmoothPixmapTransform);
42 /* 计算旋转角度 */
43 if (angle++ == 360)
44 angle = 0;
45
46 /* QPixmap 类型对象 */
47 QPixmap image;
48
49 /* 加载 */
50 image.load(":/image/cd.png");
51
52 /* QRectF 即,继承 QRect(Qt 的矩形类),F 代表精确到浮点类型 */
53 QRectF rect((this->width() - image.width()) / 2,
54 (this->height() - image.height()) / 2,
55 image.width(),
56 image.height());
57
58 /* 默认参考点为左上角原点(0,0),因为旋转需要以图形的中心为参考点,
59 * 我们使用 translate 把参考点设置为 CD 图形的中心点坐标 */
60 painter.translate(0 + rect.x() + rect.width() / 2,
61 0 + rect.y() + rect.height() / 2);
62
63 /* 旋转角度 */
64 painter.rotate(angle);
65
66 /* 现在参考点为 CD 图形的中心,我们需要把它设置回原点的位置,
67 * 所以需要减去上面加上的数 */
68 painter.translate(0 - (rect.x() + rect.width() / 2),
69 0 - (rect.y() + rect.height() / 2));
70
71 /* 画图,QPainter 提供了许多 drawX 的方法 */
72 painter.drawImage(rect, image.toImage(), image.rect());
73
74 /* 再画一个矩形 */
75 painter.drawRect(rect.toRect());
}
第 34~76 行,paintEvent()的实现。首先先指定需要画图的对象,加图片后,使用 translate()
设置参考原点,旋转一定的角度后再恢复参考原点。之后就开始画图。
第四:运行效果
编译运行程序后可以看到如下效果,CD的外框加画一个矩形,使旋转更明显。使用paintEvent 可以实现一些需要绘图的情景,它可能比 Qt 动画类更容易实现。