绘图与图表-Qt-思维导图-学习笔记

绘图与图表

在这里插入图片描述

QPainter 绘图

概述

  • 绘图系统核心类

    • QPainter: 主要用于直接操作绘图的类

    • QPaintDevice: 比 QPainter 更底层,定义了一个可以绘图的设备

    • QPainEngine: 比 QPainter 更底层,用于实现绘图设备的具体绘图过程

  • 可作为绘图“画布”的类

    • QWidget: 所有可视类控件的基类,提供了绘图区域

    • QPixmap: 用于离屏绘图的设备

    • QImage: 提供了对图像数据的操作和存储

    • QLabel: 用于显示文本或图像的控件

  • paintEvent() 事件

    • 定义: 这是一个虚函数,在 qwidget.h 头文件中使用 protected 修饰符声明

    • 作用: 当界面初始化或需要刷新时,触发绘图事件

    • 重写: 子类继承自 QWidget,可以重写这个事件来执行自定义的绘图操作

  • 触发 paintEvent() 事件

    • 初始化: 界面初始化时自动触发

    • 刷新: 需要刷新界面时,通过调用 update() 方法来触发

  • 重写 paintEvent() 的基本结构

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

    • QPainter: 创建一个 QPainter 对象,指定绘图目标为当前 Widget (this)

    • 绘图操作: 使用 QPainter 对象进行各种绘图操作(如绘制图形、文本、图像等)

应用实例

  • 使用一张CD 图片,用 QPainter 在 paintEvent()将 CD 画在窗口的中心,并且每 100ms 旋转 1 度角度

  • mainwindow.h

    • 1 #ifndef MAINWINDOW_H
      2 #define MAINWINDOW_H
      3
      4 #include
      5 #include
      6 #include
      7 #include
      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 }
      33
      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());
      76 }

    • 第 34~76 行,paintEvent()的实现

      • 首先先指定需要画图的对象,加图片后,使用 translate()
        设置参考原点,旋转一定的角度后再恢复参考原点

      • 之后就开始画图

    • 第 31 行,定时 100ms 更新一次界面

      • 因为 paintEvent 事件在构造函数执行时只会执行一次

      • 我们需要使用 update()方法来更新界面,才能看到 CD 旋转的效果

程序运行效果

  • CD 的外框加画了一个矩形,使旋转更明显

QChart 图表

概述

  • 功能概述

    • Qt Charts: 提供了方便的接口来绘制常见的图表,如曲线图、折线图、柱状图和饼状图等

    • 优点: 不需要额外学习第三方组件或开发自定义组件,Qt 的帮助文档已经详细说明了 Qt Charts 的使用方法

  • 文档参考

    • 查看 Qt 文档: 需要使用时,可以查阅官方文档获取详细的使用方法和示例
  • 继承关系

    • 理解继承关系: 通过查看类的继承关系,可以了解类的来源和结构,它们是逐步构建起来的

    • 快捷键: 在 Qt Creator 中使用快捷键 Ctrl + Shift + T,可以查看指定类的继承关系

  • 项目设置

    • 添加模块: 在项目的 .pro 文件中添加以下语句,以使用 Qt Charts 模块

    • QT += charts

  • 包含头文件和命名空间

    • 包含头文件: 在使用 Qt Charts 类时,除了包含相应的头文件外,还需要使用特定的命名空间

    • 命名空间使用方法

      • 在头文件中加上以下宏定义

        • QT_CHARTS_USE_NAMESPACE
      • 或者在头文件类外使用 using 语句

        • using namespace QtCharts;

应用实例

  • 基本流程

    • 创建必要对象

      • QSplineSeries: 表示曲线对象

      • QChart: 表示图表对象

      • QChartView: 表示图表视图对象

    • 创建坐标轴

      • 创建 QValueAxis 的 X 轴和 Y 轴对象
    • 配置图表

      • 将坐标轴添加到图表上

      • 将曲线对象添加到图表,并关联坐标轴

    • 配置视图

      • 将图表添加到图表视图中
    • 数据更新

      • 由系统生成随机数据,并定期更新曲线上的数据
  • 代码

    • 将项目文件第一行添加的代码如下

      • 1 QT += core gui charts
    • mainwindow.h

      • 1 #ifndef MAINWINDOW_H
        2 #define MAINWINDOW_H
        3 #include
        4 #include
        5 #include
        6 #include
        7 #include
        8 #include
        9 #include
        10
        11 /* 必需添加命名空间 */
        12 QT_CHARTS_USE_NAMESPACE
        13
        14 class MainWindow : public QMainWindow
        15 {
        16 Q_OBJECT
        17
        18 public:
        19 MainWindow(QWidget parent = nullptr);
        20 ~MainWindow();
        21
        22 private:
        23 /
        接收数据接口 /
        24 void receivedData(int);
        25
        26 /
        数据最大个数 /
        27 int maxSize;
        28
        29 /
        x 轴上的最大值 /
        30 int maxX;
        31
        32 /
        y 轴上的最大值 /
        33 int maxY;
        34
        35 /
        y 轴 */
        36 QValueAxis axisY;
        37
        38 /
        x 轴 /
        39 QValueAxis axisX;
        40
        41 /
        QList int 类型容器 /
        42 QList data;
        43
        44 /
        QSplineSeries 对象(曲线)
        /
        45 QSplineSeries splineSeries;
        46
        47 /
        QChart 图表 */
        48 QChart chart;
        49
        50 /
        图表视图 */
        51 QChartView chartView;
        52
        53 /
        定时器 */
        54 QTimer *timer;
        55
        56 private slots:
        57 void timerTimeOut();
        58 };
        59 #endif // MAINWINDOW_H
    • mainwindow.cpp

      • 1 #include “mainwindow.h”
        2 #include
        3 MainWindow::MainWindow(QWidget parent)
        4 : QMainWindow(parent)
        5{
        6 /
        设置最显示位置与大小 /
        7 this->setGeometry(0, 0, 800, 480);
        8 /
        最大储存 maxSize - 1 个数据 /
        9 maxSize = 51;
        10 /
        x 轴上的最大值 /
        11 maxX = 5000;
        12 /
        y 轴最大值 /
        13 maxY = 40;
        14
        15 /
        splineSeries 曲线实例化(折线用 QLineSeries) /
        16 splineSeries = new QSplineSeries();
        17 /
        图表实例化 /
        18 chart = new QChart();
        19 /
        图表视图实例化 /
        20 chartView = new QChartView();
        21
        22 /
        坐标轴 /
        23 axisY = new QValueAxis();
        24 axisX = new QValueAxis();
        25 /
        定时器 /
        26 timer = new QTimer(this);
        27
        28 /
        legend 译图例类型,以绘图的颜色区分,本例设置为隐藏 /
        29 chart->legend()->hide();
        30 /
        chart 设置标题 /
        31 chart->setTitle(“实时动态曲线示例”);
        32 /
        添加一条曲线 splineSeries /
        33 chart->addSeries(splineSeries);
        34
        35 /
        设置显示格式 /
        36 axisY->setLabelFormat(“%i”);
        37 /
        y 轴标题 /
        38 axisY->setTitleText(“温度/℃”);
        39 /
        y 轴标题位置(设置坐标轴的方向) /
        40 chart->addAxis(axisY, Qt::AlignLeft);
        41 /
        设置 y 轴范围 /
        42 axisY->setRange(0, maxY);
        43 /
        将 splineSeries 附加于 y 轴上 /
        44 splineSeries->attachAxis(axisY);
        45
        46 /
        设置显示格式 /
        47 axisX->setLabelFormat(“%i”);
        48 /
        x 轴标题 /
        49 axisX->setTitleText(“时间/ms”);
        50 /
        x 轴标题位置(设置坐标轴的方向) /
        51 chart->addAxis(axisX, Qt::AlignBottom);
        52 /
        设置 x 轴范围 /
        53 axisX->setRange(0, maxX);
        54 /
        将 splineSeries 附加于 x 轴上 /
        55 splineSeries->attachAxis(axisX);
        56
        57 /
        将图表的内容设置在图表视图上 /
        58 chartView->setChart(chart);
        59 /
        设置抗锯齿 /
        60 chartView->setRenderHint(QPainter::Antialiasing);
        61
        62 /
        设置为图表视图为中心部件 /
        63 setCentralWidget(chartView);
        64
        65 /
        定时 200ms /
        66 timer->start(200);
        67 /
        信号槽连接 /
        68 connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeOut()));
        69
        70 /
        设置随机种子,随机数初始化 /
        71 qsrand(time(NULL));
        72 }
        73
        74 MainWindow::~MainWindow()
        75 {
        76 }
        77
        78 void MainWindow::timerTimeOut()
        79 {
        80 /
        产生随机 0~maxY 之间的数据 /
        81 receivedData(qrand() % maxY );
        82 }
        83
        84 void MainWindow::receivedData(int value)
        85 {
        86 /
        将数据添加到 data 中 /
        87 data.append(value);
        88
        89 /
        当储存数据的个数大于最大值时,把第一个数据删除 /
        90 while (data.size() > maxSize) {
        91 /
        移除 data 中第一个数据 /
        92 data.removeFirst();
        93 }
        94
        95 /
        先清空 /
        96 splineSeries->clear();
        97
        98 /
        计算 x 轴上的点与点之间显示的间距 /
        99 int xSpace = maxX / (maxSize - 1);
        100
        101 /
        添加点,xSpace * i 表示第 i 个点的 x 轴的位置 */
        102 for (int i = 0; i < data.size(); ++i) {
        103 splineSeries->append(xSpace * i, data.at(i));
        104 }
        105 }

      • 第 84~105 行,是实现曲线移动的重要代码

        • 算法逻辑

          • 当数据点个数超过最大值时,删除第一个数据点

          • 通过反复删除和添加数据点,控制数据点数量

        • 数据移动实现

          • 旧数据点的删除和新数据点的添加,使曲线在图表视图中动态更新,实现数据移动的视觉效果

程序运行效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木木不迷茫(˵¯͒¯͒˵)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值