使用Qt实现实时数据动态绘制的折线图示例
基于Qt的 QChartView 和定时器来动态绘制折线图。它通过动画的方式逐步将数据点添加到图表上,并动态更新坐标轴的范围,提供了一个可以实时更新数据的折线图应用。以下是对代码的详细介绍及其功能解析:

代码概述
该程序使用Qt的 QChartView 作为图表绘制的基础,结合 QLineSeries 或 QSplineSeries 来绘制折线或样条曲线。程序通过定时器 (QTimer) 控制数据点的动态绘制,并在绘图过程中实时更新坐标轴的显示范围。
主要功能
- 动态创建系列:可以动态创建多个曲线系列(
QLineSeries或QSplineSeries),每个系列对应一条折线或样条曲线。 - 动态添加数据点:通过
addPointAnimated()函数,可以为每个系列动态添加数据点,并通过动画效果逐步连接新数据点。 - 定时更新:使用
QTimer每隔一段时间调用animateDrawing()函数,逐步将新点连接到已有的曲线上。 - 自动调整坐标轴范围:在绘制过程中,如果新点超出了当前坐标轴范围,坐标轴会自动调整以适应新的数据点。
代码结构
1. DynamicChart 类构造函数
DynamicChart::DynamicChart(QWidget *parent): QChartView(new QChart(), parent), m_chart(this->chart())
{m_chart->setTitle("Dynamic Data Plot");m_chart->legend()->hide();setRenderHint(QPainter::Antialiasing);// 设置图表主题和隐藏图例m_chart->setTheme(QChart::ChartTheme::ChartThemeDark);// 创建共用的坐标轴axisX = new QValueAxis();axisX->setRange(0, 100);m_chart->addAxis(axisX, Qt::AlignBottom);axisY = new QValueAxis();axisY->setRange(0, 100);m_chart->addAxis(axisY, Qt::AlignLeft);// 设置定时器connect(&timer, &QTimer::timeout, this, &DynamicChart::animateDrawing);timer.setInterval(30); // 动画更新间隔为30毫秒resize(500,500);
}
该构造函数中设置了图表的主题、坐标轴、以及定时器,定时器的作用是每隔30毫秒触发 animateDrawing() 函数,用于动态绘制数据。
2. createSeries() 函数
void DynamicChart::createSeries(int seriesId, const QString &name)
{
#ifdef LINEQLineSeries *series = new QLineSeries();
#elseQSplineSeries *series = new QSplineSeries();
#endifseries->setName(name);m_chart->addSeries(series);// 使用共用的坐标轴series->attachAxis(axisX);series->attachAxis(axisY);seriesMap.insert(seriesId, series);
}
该函数负责创建新的系列(折线或样条曲线),并将其添加到图表中。 seriesId 用于标识不同的曲线,name 则用于显示系列的名称。系列将共享同一套坐标轴。
3. addPointAnimated() 函数
void DynamicChart::addPointAnimated(int seriesId, const QPointF &point)
{if (!seriesMap.contains(seriesId)) return;
#ifdef LINEQLineSeries *series = seriesMap[seriesId];
#elseQSplineSeries *series =seriesMap[seriesId];
#endifif (!series->points().isEmpty()) {lastPoint = series->points().last();} else {lastPoint = point; // 第一个点直接添加series->append(point);}newPoint = point;currentSeriesId = seriesId;currentStep = 0;stepsCount = 10; // 分10步完成连线timer.start();
}
该函数用于为指定的系列添加新点,并通过动画效果使新点逐步出现在图表上。它会计算新点与最后一个点之间的插值,并逐步绘制曲线。
4. animateDrawing() 函数
void DynamicChart::animateDrawing()
{
#ifdef LINEQLineSeries *series = seriesMap[currentSeriesId];
#elseQSplineSeries *series =seriesMap[currentSeriesId];
#endifif (currentStep >= stepsCount) {timer.stop();series->append(newPoint);return;}qreal x = lastPoint.x() + (newPoint.x() - lastPoint.x()) * currentStep / stepsCount;qreal y = lastPoint.y() + (newPoint.y() - lastPoint.y()) * currentStep / stepsCount;series->append(x, y);// 动态更新坐标轴if (x > axisX->max()) {axisX->setMax(x + 10);}if (y > axisY->max() || y < axisY->min()) {axisY->setMax(qMax(y + 10, axisY->max()));axisY->setMin(qMin(y - 10, axisY->min()));}currentStep++;
}
该函数实现了通过定时器触发的动态绘制。它逐步将新点与前一个点连接,并动态调整坐标轴的范围以适应新增数据。
主窗口逻辑
最后的代码片段展示了如何使用 DynamicChart 类创建一个包含多个曲线的图表,并通过按钮控制定时器的启动与停止:
setMinimumSize(QSize(800,500));
chartView = new DynamicChart(this);
chartView->createSeries(1, "Test Series 1");
chartView->createSeries(2, "Test Series 2");
chartView->createSeries(3, "Test Series 3");
chartView->createSeries(4, "Test Series 4");QTimer *timer = new QTimer;
connect(timer, &QTimer::timeout, this, [=]()
{int m_id = QRandomGenerator::global()->bounded(1, 5);chartView->addPointAnimated(m_id, QPointF(m_index++, QRandomGenerator::global()->bounded(100)));
});startButton = new QRadioButton("StartDrawing", this);
connect(startButton, &QRadioButton::clicked, [=](bool arg)
{if (arg)timer->start(100);elsetimer->stop();
});
通过 QRadioButton 控制定时器的启停,点击按钮后,程序将开始在图表上随机添加点,并动态绘制折线或样条曲线。
结论
此程序通过Qt的 QChartView 和定时器,实现了一个能够动态绘制多条曲线的折线图表。通过定时器控制数据点的逐步绘制,并结合坐标轴的动态更新,使得该图表在绘图过程中能够自动适应数据的变化。这种方式适用于需要实时显示数据变化的场景,如传感器数据的实时监控或动态性能分析等。
相关文章:
使用Qt实现实时数据动态绘制的折线图示例
基于Qt的 QChartView 和定时器来动态绘制折线图。它通过动画的方式逐步将数据点添加到图表上,并动态更新坐标轴的范围,提供了一个可以实时更新数据的折线图应用。以下是对代码的详细介绍及其功能解析: 代码概述 该程序使用Qt的 QChartView…...
【人人保-注册安全分析报告-无验证方式导致安全隐患】
前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…...
Redis6 多线程模型
优质博文:IT-BLOG-CN 一、单线程的优缺点 对于一个请求操作Redis主要做3件事情:从客户端读取数据/解析、执行Redis命令、回写数据给客户端。所以主线程其实就是把所有操作的这3件事情串行一起执行,因为是基于内存,所以执行速度非…...
Python的异步编程
什么是协程? 协程不是计算机系统提供,程序员人为创造。 协程也可以被称为微线程,是一种用户态内的上下文切换技术。简而言之,其实就是通过一个线程实现代码块相互切换执行。 实现协程有那么几种方法: greenlet&…...
初识Linux · 进程等待
目录 前言: 进程等待是什么 为什么需要进程等待 进程等待都在做什么 前言: 通过上文的学习,我们了解了进程终止,知道终止是在干什么,终止的三种情况,以及有了退出码,错误码的概念ÿ…...
面向对象建模
UML 关系 UML 关系主要有:依赖、关联、聚合、组合、实现、继承。 类图 #mermaid-svg-jcAjcVcPmgmWDpcI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-jcAjcVcPmgmWDpcI .error-icon{fill:#552222;}#m…...
MetaJUI v0.4 遇到的一些问题及解决办法记录
1、Unity3d 版本 2022.3.29f1。 2、MetaJUI v0.4 的下载,https://download.csdn.net/download/xingchengaiwei/89334848 3、将MetaJUI v0.4解压,用Unity3d 打开项目,会出现如下问题,按照图中提示操作即可。 4、打开工程后会出现…...
从零开始学习OMNeT++系列第二弹——新建一个OMNeT++的工程
上一篇第一弹介绍了OMNeT是什么以及如何安装OMNeT,现在来说一下如何新建一个自己的OMNeT的工程。 在 Omnet安装完成后,samples/tictoc 中有该例子的完整文件,你可以立刻运行该文件看他是怎么工作的,不过更推荐按接下来的步骤一步…...
【Android】布局优化—include,merge,ViewStub的使用方法
引言 1.重要性 在Android应用开发中,布局是用户界面的基础。一个高效的布局不仅能提升用户体验,还能显著改善应用的性能。随着应用功能的复杂性增加,布局的优化变得尤为重要。优化布局能够减少渲染时间,提高响应速度,…...
传奇外网架设教程带图文解说—Gee引擎
架设前准备工作: ①通过百度网盘下载版本、补丁、客户端和DBC2000。版本解压到D盘,客户端解压到D盘或是E盘,补丁先不解压 ②安装和配置DBC2000,有些版本不一定用的是DBC2000数据库,看引擎默认的数据库是哪个 DBC数据…...
MySQL | excel数据输出insert语句
需求 在日常生产运维过程中,有很多需要进行人工梳理的excel数据,到了研发这一侧需要转为sql语句进行数据修正,如何输出insert插入语句? 方案 在空白列插入,选择需要的列 "INSERT INTO tab_name1 (name, desc) …...
足球青训俱乐部管理:Spring Boot技术驱动
摘 要 随着社会经济的快速发展,人们对足球俱乐部的需求日益增加,加快了足球健身俱乐部的发展,足球俱乐部管理工作日益繁忙,传统的管理方式已经无法满足足球俱乐部管理需求,因此,为了提高足球俱乐部管理效率…...
一次实践:给自己的手机摄像头进行相机标定
文章目录 1. 问题引入2. 准备工作2.1 标定场2.2 相机拍摄 3. 基本原理3.1 成像原理3.2 畸变校正 4. 标定解算4.1 代码实现4.2 详细解析4.2.1 解算实现4.2.2 提取点位 4.3 解算结果 5. 问题补充 1. 问题引入 不得不说,现在的计算机视觉技术已经发展到足够成熟的阶段…...
【docker学习】Linux系统离线方式安装docker环境方法
centos7-linux安装docker(离线方式) 下载docker的安装文件 https://download.docker.com/linux/static/stable/x86_64/ 下载的是:docker-18.06.3-ce.tgz 这个压缩文件 将docker-18.06.3-ce.tgz文件上传到centos7-linux系统上,用ftp工具上传即可 解压…...
vscode开发uniapp安装插件指南
安装vuets的相关插件 首先是vue的相关插件,目前2024年9月应该是vue-offical 安装uniapp开发插件 uni-create-view :快速创建 uni-app 页面 安装uni-create-view之后修改插件拓展设置 勾选第一个选择创建视图时创建同名文件夹 选择第二个创建文件夹中生…...
Elasticsearch7.7.1集群不能相互发现的问题解决以及Elasticsearch7.7.1安装analysis-ik中文分词插件的应用
一、Elasticsearch7.7.1集群不能相互发现的问题解决 在使用elasticsearch7.7.1搭建集群,使用了3台服务器作为节点,但在搭建的过程中发现每台服务器的elasticsearch服务都正常,但是不能相互发现,期间进行了一些配置的修改偶尔出现了…...
蓝牙Mesh介绍
蓝牙Mesh(Bluetooth Mesh)是一种基于蓝牙技术的无线通信网络拓扑,用于在设备之间创建大规模的多点到多点网络。蓝牙Mesh网络可以让多个蓝牙设备相互通信和协作,适合需要高覆盖范围和高可靠性的场景,例如智能家居、工业…...
Qt 窗口中鼠标点击事件的坐标探讨
// 鼠标点击事件 void Widget::mousePressEvent(QMouseEvent *event) {/*event->pos()、event->windowPos()和event->localPos()都表示鼠标点击位置在窗口中的位置,它们的值都是一样的,区别在于event->pos()是QPoint类型,event-&…...
服务器虚拟化的全面指南
1. 引言 在数字化转型的浪潮中,服务器虚拟化成为现代IT基础设施的核心组成部分。它通过将物理服务器资源分割成多个虚拟资源,极大地提高了资源利用率和灵活性。本篇文章将深入探讨服务器虚拟化的概念、优势、挑战、技术工具、最佳实践及未来发展趋势。 …...
Linux启动mysql报错
甲方公司意外停电,所有服务器重启后,发现部署在Linux上的mysql数据库启动失败.再加上老员工离职,新接手项目,对Linux系统了解不多,解决起来用时较多,特此记录。 1.启动及报错 1.1 启动语句1 启动语句1&a…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
