QT中使用图表之QChart绘制动态折线图

使用QChart绘制一个随着时间的变化而动态显示的折线图

每一秒增加1个点,总共显示10s内的数据

显然x轴我们使用日期时间轴

同时使用1个定时器,每隔1秒往折线系列中添加1个数据进去

步骤如下:

1、创建图表视图

cpp 复制代码
//1、创建图表视图
QChartView* view=new QChartView(this);

2、创建图表,并将图表设置给视图

cpp 复制代码
//2.创建图表
QChart * chart = new QChart();

//3.将图表设置给图表视图
view -> setChart(chart);

 //设置标题
chart->setTitle("动态折线图");
chart->legend()->show();//显示或者隐藏图例(默认显示)

3、创建x轴(采用QDateTimeAxis日期时间轴),将x轴加到图表中,并设置x的范围为[当前时间,当前时间往后推10s]

cpp 复制代码
//构建x轴-日期时间轴
QDateTimeAxis * axisX = new QDateTimeAxis(this);
axisX -> setTitleText("时间轴");
QDateTime min = QDateTime::currentDateTime(); //当前时间
QDateTime max = min.addSecs(10); //当前时间+10s
axisX -> setRange(min, max); //设置范围,[当前时间,当前时间+10s]
axisX -> setTickCount(11);
axisX -> setFormat("hh:mm:ss"); //设置刻度值的格式
axisX -> setLabelsAngle(45);
chart -> addAxis(axisX, Qt::AlignBottom);

4、创建y轴,将y轴加到图标中

cpp 复制代码
//构建y轴-数值轴
QValueAxis * axisY = new QValueAxis(this);
axisY -> setRange(1000, 2000);
axisY -> setTickCount(11);
axisY -> setTitleText("Y轴");
chart -> addAxis(axisY, Qt::AlignLeft);

5、创建折线系列,并添加到图表中,此时先不往折线系列中添加数据

cpp 复制代码
//构建折线系列
QLineSeries * line = new QLineSeries(this);
line -> setName("时间轴");
chart -> addSeries(line);

6、将x轴和y轴和折线系列进行关联

cpp 复制代码
line -> attachAxis(axisX);
line -> attachAxis(axisY);

7、创建定时器,并开启定时器,在定时器超时信号的槽函数中:

  • 往折线系列中添加数据

  • 并且x值(即当前时间)超过了最开始设定的最大值时,更新x轴的范围,新的范围为[当前时间往前推10s,当前时间]

  • 同时删除不可见的点,防止内存一直增长

    cpp 复制代码
    //定时器中动态添加数据
    QTimer * t = new QTimer(this);
    t -> setTimerType(Qt::PreciseTimer);
    connect(t, & QTimer::timeout, this, [ = ]() {
    
        auto x = QDateTime::currentMSecsSinceEpoch(); //获取当前时间的毫秒数
        auto y = QRandomGenerator::global() -> bounded(1000, 2000); //y值采用随机数
    
        //第一次触发这个槽函数时更新一下范围,解决开头有几个点没有的bug
        //因为前面设置x轴范围获取的时间和定时器超时的时间点有10ms的间隔,毕竟x轴的精度是毫秒级别
        //这个更新只执行一次
        static std::once_flag once;
        std::call_once(once, [ = ]() {
            QDateTime min_ = QDateTime::fromMSecsSinceEpoch(x); //当前时间
            QDateTime max_ = min_.addSecs(10); //当前时间+10s
            axisX -> setRange(min_, max_); //设置范围,10s的范围
        });
    
        //添加数据
        line -> append(x, y);
    
        QDateTime max = axisX -> max();
    
        //当前x值超过了x轴的最大值
        if (x > max.toMSecsSinceEpoch()) {
            QDateTime new_max = QDateTime::fromMSecsSinceEpoch(x);
            QDateTime new_min = max.addSecs(-10);
    
            //更新最大最小值,范围始终保持10s,更新x轴最大值为新的当前毫秒数
            axisX -> setRange(new_min, new_max);
    
            //删除不可见的点,否则点数越来越多,内存耗尽
            //每次删除第一个点
            line -> removePoints(0, 1);
        }
    });
    
    //开启定时器
    t -> start(10); //10ms增加一个点

    完整代码:

cpp 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

#include<QtCharts>

#include<QHBoxLayout>

#include<QPieSlice>

#include<QPieSeries>

#include<QBarSeries>

#include<QBarSet>

#include<QAreaSeries>

class Widget: public QWidget {
    Q_OBJECT

    public:
        Widget(QWidget * parent = nullptr): QWidget(parent) {
            resize(800, 600);
            QHBoxLayout * h_box = new QHBoxLayout(this);
            drawDynamicLineSeries();

        }
        ~Widget() =default;

    //绘制动态折线图
    void drawDynamicLineSeries() {
        //1、创建图表视图
        QChartView * view = new QChartView(this);

        this -> layout() -> addWidget(view);

        //2.创建图表
        QChart * chart = new QChart();

        //3.将图表设置给图表视图
        view -> setChart(chart);

        //设置标题
        chart -> setTitle("动态折线图");
        chart -> legend() -> show(); //显示或者隐藏图例(默认显示)

        //构建x轴-日期时间轴
        QDateTimeAxis * axisX = new QDateTimeAxis(this);
        axisX -> setTitleText("时间轴");
        QDateTime min = QDateTime::currentDateTime(); //当前时间
        QDateTime max = min.addSecs(10); //当前时间+10s
        axisX -> setRange(min, max); //设置范围,[当前时间,当前时间+10s]
        axisX -> setTickCount(11);
        axisX -> setFormat("hh:mm:ss"); //设置刻度值的格式
        axisX -> setLabelsAngle(45);
        chart -> addAxis(axisX, Qt::AlignBottom);

        //构建y轴-数值轴
        QValueAxis * axisY = new QValueAxis(this);
        axisY -> setRange(1000, 2000);
        axisY -> setTickCount(11);
        axisY -> setTitleText("Y轴");
        chart -> addAxis(axisY, Qt::AlignLeft);


        //构建折线系列
        QLineSeries * line = new QLineSeries(this);
        line -> setName("时间轴");
        chart -> addSeries(line);
        line -> attachAxis(axisX);
        line -> attachAxis(axisY);

        //定时器中动态添加数据
        QTimer * t = new QTimer(this);
        t -> setTimerType(Qt::PreciseTimer);
        connect(t, & QTimer::timeout, this, [ = ]() {

            auto x = QDateTime::currentMSecsSinceEpoch(); //获取当前时间的毫秒数
            auto y = QRandomGenerator::global() -> bounded(1000, 2000); //y值采用随机数

            //第一次触发这个槽函数时更新一下范围,解决开头有几个点没有的bug
            //因为前面设置x轴范围获取的时间和定时器超时的时间点有10ms的间隔,毕竟x轴的精度是毫秒级别
            //这个更新只执行一次
            static std::once_flag once;
            std::call_once(once, [ = ]() {
                QDateTime min_ = QDateTime::fromMSecsSinceEpoch(x); //当前时间
                QDateTime max_ = min_.addSecs(10); //当前时间+10s
                axisX -> setRange(min_, max_); //设置范围,10s的范围
            });

            //添加数据
            line -> append(x, y);

            QDateTime max = axisX -> max();

            //当前x值超过了x轴的最大值
            if (x > max.toMSecsSinceEpoch()) {
                QDateTime new_max = QDateTime::fromMSecsSinceEpoch(x);
                QDateTime new_min = max.addSecs(-10);

                //更新最大最小值,范围始终保持10s,更新x轴最大值为新的当前毫秒数
                axisX -> setRange(new_min, new_max);

                //删除不可见的点,否则点数越来越多,内存耗尽
                //每次删除第一个点
                line -> removePoints(0, 1);
            }
        });

        //开启定时器
        t -> start(10); //10ms增加一个点

    }

};
#endif // WIDGET_H
相关推荐
小俊俊的博客1 小时前
海康RGBD相机使用C++和Opencv采集图像记录
c++·opencv·海康·rgbd相机
7yewh1 小时前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
_WndProc1 小时前
C++ 日志输出
开发语言·c++·算法
薄荷故人_2 小时前
从零开始的C++之旅——红黑树及其实现
数据结构·c++
m0_748240022 小时前
Chromium 中chrome.webRequest扩展接口定义c++
网络·c++·chrome
qq_433554542 小时前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
努力学习编程的伍大侠2 小时前
基础排序算法
数据结构·c++·算法
yuyanjingtao2 小时前
CCF-GESP 等级考试 2023年9月认证C++四级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
闻缺陷则喜何志丹3 小时前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
charlie1145141913 小时前
C++ STL CookBook
开发语言·c++·stl·c++20