大家好,今天主要和大家聊一聊,如何使用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 动画类更容易实现。