[Introduction to Embedded Qt Development] How to use Qt for drawing - QPainter drawing

        There are many drawings and charts in embedded, especially charts. The "chart line/curve chart/pie chart, etc." that we often see in stocks can be realized with Qt charts. Contents of Drawings and Charts This chapter mainly introduces the basic operations of drawing and charts, and presents the usage of drawing and charts with simple examples.

QPainter drawing

        All drawing in Qt, such as the display of a button and a Label, is performed by the drawing system. The painting system is based on the QPainter, QPaintDevice and QPainEngine classes. QPainter is a class that can be directly used to operate drawing, and both QPaintDevice and QPainEngine are lower than QPainter. We only need to understand QPaintDevice and QPainEngine. The following figure can be used to show their relationship.

        Generally used for display classes, such as QWidget, QPixmap, QImage, Qlabel and other visual class controls can act as the "canvas" of the drawing area, and classes inherited from QWidget have virtual void paintEvent(QPaintEvent *event); attribute. The paintEvent() is a virtual function, which is under the protected: modifier of the qwidget.h header file.

        The paintEvent() event can be overridden. (Explanation: What is a drawing event? It can be understood that the event will only be executed when the interface is initialized or needs to be refreshed, that is to say, the drawing event will be executed when the construction object is instantiated. If the interface needs to be refreshed, we can use the update() method to execute paintEvent() event).

        The paintEvent() event is an interface provided by the parent class QWidget to the subclass, and it is defined as empty in the parent class, so it can be said that the paintEvent() event is specially used for drawing pictures by the subclass.

        The basic structure of the paintEvent() event rewritten in the subclass is as follows:

void Widget::paintEvent(QPaintEvent *)
{
    /* 指定画图的对象,this 代表是本 Widget */
    QPainter painter(this);
    // 使用 painter 在对象上绘图...
}

Applications

        The purpose of this example: to quickly understand the use of the paintEvent() event.

        Project name: qpainter. This example uses a CD picture, uses QPainter to draw the CD at the center of the window in paintEvent(), and rotates it by 1 degree every 100ms. So the CD appears to be rotated.

        The specific code of the header file "mainwindow.h" is as follows.

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QPainter>
#include <QPaintEvent>
#include <QTimer>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    /* 重写父类下的protected方法*/
protected:
    void paintEvent(QPaintEvent *);

private:
    /* 定时器,用于定时更新界面 */
    QTimer *timer;
    /* 角度 */
    int angle;

private slots:
    /* 槽函数 */
    void timerTimeOut();

};
#endif // MAINWINDOW_H

        Because paintEvent() is a virtual method (virtual function) under the protected modifier of the parent class QWidget, it is recommended to also write it under the protected modifier under the subclass when rewriting.

        The specific code in the source file "mainwindow.cpp" is as follows.

#include "mainwindow.h"
#include "QDebug"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    /* 设置主窗口位置及颜色 */
    this->setGeometry(0, 0, 800, 480);
    setPalette(QPalette(Qt::gray));
    setAutoFillBackground(true);

    /* 定时器实例化 */
    timer = new QTimer(this);

    /* 默认角度为0 */
    angle = 0;

    /* 定时100ms */
    timer->start(100);

    /* 信号槽连接 */
    connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeOut()));
}

MainWindow::~MainWindow()
{
}

void MainWindow::timerTimeOut()
{
    /* 需要更新界面,不设置不更新 */
    this->update();
}

void MainWindow::paintEvent(QPaintEvent *)
{
    /* 指定父对象,this指本窗口 */
    QPainter painter(this);

    /* 设置抗锯齿,流畅转换 */
    painter.setRenderHints(QPainter::Antialiasing
                           | QPainter::SmoothPixmapTransform);
    /* 计算旋转角度 */
    if (angle++ == 360)
        angle = 0;

    /* QPixmap类型对象 */
    QPixmap image;

    /* 加载 */
    image.load(":/image/cd.png");

    /* QRectF即,继承QRect(Qt的矩形类),F代表精确到浮点类型 */
    QRectF rect((this->width() - image.width()) / 2,
                (this->height() - image.height()) / 2,
                image.width(),
                image.height());

    /* 默认参考点为左上角原点(0,0),因为旋转需要以图形的中心为参考点,
     * 我们使用translate把参考点设置为CD图形的中心点坐标 */
    painter.translate(0 + rect.x() + rect.width() / 2,
                      0 + rect.y() + rect.height() / 2);

    /* 旋转角度 */
    painter.rotate(angle);

    /* 现在参考点为CD图形的中心,我们需要把它设置回原点的位置,
     * 所以需要减去上面加上的数 */
    painter.translate(0 - (rect.x() + rect.width() / 2),
                      0 - (rect.y() + rect.height() / 2));

    /* 画图,QPainter提供了许多drawX的方法 */
    painter.drawImage(rect, image.toImage(), image.rect());

    /* 再画一个矩形 */
    painter.drawRect(rect.toRect());
}

        First implement paintEvent(). First specify the object that needs to be drawn, and after adding the picture, use translate() to set the reference origin, rotate a certain angle and then restore the reference origin. Then start drawing. It may be difficult to understand at the reference point, so please analyze it according to the above notes.

        Then, update the interface once every 100ms. Because the paintEvent event will only be executed once when the constructor is executed. We need to use the update() method to update the interface in order to see the effect of CD rotation.

Program running effect

        After compiling and running the program, you can see the following effect. A rectangle is added to the outer frame of the CD to make the rotation more obvious. Use paintEvent to achieve some scenarios that require drawing, which may be easier to implement than Qt animation classes. Combined with Qt's paintbrush, it is also possible to design a drawing software, thanks to paintEvent() and QPainter, which make interface development more possible. In interface design, paintEvent() is often used to redraw the interface, and we need to master this part of the content.

 

Guess you like

Origin blog.csdn.net/cj_lsk/article/details/131557274