使用Qt实现实时数据动态绘制的折线图示例

news2024/10/2 5:04:48

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

代码概述

该程序使用Qt的 QChartView 作为图表绘制的基础,结合 QLineSeriesQSplineSeries 来绘制折线或样条曲线。程序通过定时器 (QTimer) 控制数据点的动态绘制,并在绘图过程中实时更新坐标轴的显示范围。

主要功能
  • 动态创建系列:可以动态创建多个曲线系列(QLineSeriesQSplineSeries),每个系列对应一条折线或样条曲线。
  • 动态添加数据点:通过 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 LINE
    QLineSeries *series = new QLineSeries();
#else
    QSplineSeries *series = new QSplineSeries();
#endif
    series->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 LINE
    QLineSeries *series = seriesMap[seriesId];
#else
    QSplineSeries *series =seriesMap[seriesId];
#endif

    if (!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 LINE
    QLineSeries *series = seriesMap[currentSeriesId];
#else
    QSplineSeries *series =seriesMap[currentSeriesId];
#endif
    if (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);
    else
        timer->stop();
});

通过 QRadioButton 控制定时器的启停,点击按钮后,程序将开始在图表上随机添加点,并动态绘制折线或样条曲线。

结论

此程序通过Qt的 QChartView 和定时器,实现了一个能够动态绘制多条曲线的折线图表。通过定时器控制数据点的逐步绘制,并结合坐标轴的动态更新,使得该图表在绘图过程中能够自动适应数据的变化。这种方式适用于需要实时显示数据变化的场景,如传感器数据的实时监控或动态性能分析等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2183795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python报错已解决】 Encountered error while trying to install package.> lxml

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

黑马linux笔记(转载)

学习链接 视频链接&#xff1a;黑马程序员新版Linux零基础快速入门到精通 原文链接&#xff1a;黑马程序员新版Linux零基础快速入门到精通——学习笔记 黑马Linux笔记 文章目录 学习链接01初识Linux1.1、操作系统概述1.1.1、硬件和软件1.1.2、操作系统1.1.3、常见操作系统 1.…

10/01赛后总结

T1隔离 题目传送门&#xff1a;隔离http://bbcoj.cn/contest/1027/problem/1 实在是太刁钻了&#xff0c;有两种情况没有考虑&#xff1a; 1.隔离后做完全部的是再回去 2.在路程上花的时间如果大于在隔离一次花的时间&#xff0c;那还不如隔离&#xff0c;然后做完全部的事…

阿里云域名注册购买和备案

文章目录 1、阿里云首页搜索 域名注册2、点击 控制台3、域名控制台 1、阿里云首页搜索 域名注册 2、点击 控制台 3、域名控制台

聊聊Mysql的MVCC

1 什么是MVCC&#xff1f; MVCC&#xff0c;是Multiversion Concurrency Control的缩写&#xff0c;翻译过来是多版本并发控制&#xff0c;和数据库锁一样&#xff0c;他也是一种并发控制的解决方案。 我们知道&#xff0c;在数据库中&#xff0c;对数据的操作主要有2种&#…

Java项目实战II基于Java+Spring Boot+MySQL的购物推荐网站的设计与实现(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者 一、前言 随着互联网技术的飞速发展&#xff0c;电子商务已成为人们日常生活中不可或缺的一部分。然而&#xf…

论文笔记:基于细粒度融合网络和跨模态一致性学习的多模态假新闻检测

整理了MMAsia2023 Cross-modal Consistency Learning with Fine-grained Fusion Network for Multimodal Fake News Detection 论文的阅读笔记 背景模型筛选模块 实验消融实验超参数讨论可视化 背景 尽管以往的工作已经观察到假新闻中文字与图像的不匹配&#xff0c;但他们仍致…

大数据毕业设计选题推荐-民族服饰数据分析系统-Python数据可视化-Hive-Hadoop-Spark

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

DNS with libevent

DNS with libevent: high-level and low-level functionality libevent提供了少量用于解析DNS名字的API&#xff0c;以及用于实现简单DNS服务器的机制。 我们从用于名字查询的高层机制开始介绍&#xff0c;然后介绍底层机制和服务器机制。 Portable blocking name resolution…

八、SPOOLING技术

1.早期脱机技术 外围控制机更高速的设备--磁带 作用:缓解设备与CPU的速度矛盾&#xff0c;实现预输入、缓输出 批处理阶段引入了脱机输入/输出技术(用磁带完成): 引入脱机技术后&#xff0c;缓解了CPU与慢速I/O设备的速度矛盾。另一方面&#xff0c;即使CPU在忙碌&#xff0…

【Windows】在任务管理器中隐藏进程

在此前的一篇&#xff0c;我们已经介绍过了注入Dll 阻止任务管理器结束进程 -- Win 10/11。本篇利用 hook NtQuerySystemInformation 并进行断链的方法实现进程隐身&#xff0c;实测支持 taskmgr.exe 的任意多进程隐身。 任务管理器 代码&#xff1a; // dllmain.cpp : 定义 …

MongoDB微服务部署

一、安装MongoDB 1.在linux中拉去MongoDB镜像文件 docker pull mongo:4.4.18 2. 2.创建数据挂载目录 linux命令创建 命令创建目录: mkdir -p /usr/local/docker/mongodb/data 可以在sshclient工具查看是否创建成功。 进入moogodb目录&#xff0c;给data赋予权限777 cd …

2024-09-04 深入JavaScript高级语法十五——浏览器原理-V8引擎-js执行原理

目录 1、浏览器的工作原理1.1、认识浏览器内核1.2、浏览器渲染过程 2、JS引擎2.1、认识 JavaScript 引擎2.2、浏览器内核和JS引擎的关系2.3、V8引擎的原理2.4、V8引擎的架构2.5、V8执行的细节 3、全局代码的执行过程3.1、初始化全局对象3.2、执行上下文栈&#xff08;调用栈&am…

World of Warcraft [CLASSIC][80][Grandel] Call to Arms: Victory in Wintergrasp

Wintergrasp 冬拥湖 120 VS 120 Victory in Wintergrasp - Quest - 魔兽世界怀旧服WLK3.35数据库_巫妖王之怒80级魔兽数据库_wlk数据库

逆向-下字符串查找的条件断点

为了跟踪console程序在访问某个文件时失败的问题&#xff0c;在内核中下了断点&#xff0c;但是内核中文件部分调用太频繁了&#xff0c;无法等到自己的文件。所以最好还是根据条件来下断点。 程序如下 想要在FileName是指定文件时停下来&#xff0c;例如FileName是c:\temp\f…

「轻盈」之旅:OOM故障重现与解决

前期准备 本项目均采用 VisualVM 2.1.10 进行dump文件的分析。JDK1.8及之前所在目录的bin目录下有自带的VisualVM&#xff0c;JDK1.8以后需要自行手动安装下载。 下载地址&#xff1a;https://visualvm.github.io/download.html IDEA插件配置&#xff1a;在Plugins里搜索visual…

2-109 基于matlab-GUI的BP神经网络

基于matlab-GUI的BP神经网络&#xff0c;10种不同分布的数据样本&#xff0c;9种不同的激活函数&#xff0c;可更改升级网络结构参数&#xff0c;对比各种方法参数下的训练测试效果&#xff0c;实时显示预测过程。程序已调通&#xff0c;可直接运行。 下载源程序请点链接&…

【简介Sentinel-1】

Sentinel-1是欧洲航天局哥白尼计划&#xff08;GMES&#xff09;中的地球观测卫星&#xff0c;由Sentinel-1A和Sentinel-1B两颗卫星组成。以下是对Sentinel-1的详细介绍&#xff1a; 一、基本信息 卫星名称&#xff1a;Sentinel-1 所属计划&#xff1a;欧洲航天局哥白尼计划…

【CSS】兼容处理

兼容前缀兼容查询 由于不同浏览器对CSS标准的支持程度不同&#xff0c;可能会导致在不同浏览器中出现样式差异。为了解决这个问题&#xff0c;需要采取一些措施来提高CSS的兼容性 兼容前缀 兼容前缀针对的浏览器-webkit-WebKit 内核浏览器&#xff0c;如&#xff1a;Safari 、…

.NET Core 集成 MiniProfiler性能分析工具

前言&#xff1a; 在日常开发中&#xff0c;应用程序的性能是我们需要关注的一个重点问题。当然我们有很多工具来分析程序性能&#xff1a;如&#xff1a;Zipkin等&#xff1b;但这些过于复杂&#xff0c;需要单独搭建。 MiniProfiler就是一款简单&#xff0c;但功能强大的应用…