【转载】Qt QCustomPlot 使用整理

news/2025/11/27 13:15:24/文章来源:https://www.cnblogs.com/JiaYuBaoBao/p/19277113

  QCustomPlot 是一个比较小的 QT 图表插件。使用时,我们在程序中写完相关调用的代码后,只需将 QCunstomPlot.cpp 和 QCustomPlot.h 两个文件加入工程,正常编译即可。看起来使用挺方便。对于简单的,效率不高的数据可视化需求,基本能满足。这里把使用该插件的一些经验做简单记录。

1. 插件的声明

  QCustomPlot 的官方文档里,只介绍了在 QT Designer 中 prompt 插件的方法,如果是使用可视化窗口设计界面,这样就足够了。但是,如果用纯代码来设计界面,就麻烦了,针对初学者的文档里,并没有提到怎么 new 出一个 QCustomPlot 实体。

  根据官方文档在图形界面中prompt 插件后,编译,查看designer生成的 ui_xxxx.h 文件,在里面发现了声明方法。下面是我自己在项目里的代码,已测试可行。

复制代码
 1   QWidget *paintArea = new QWidget;
 2     QCustomPlot *myPlot = new QCustomPlot(paintArea);
 3     myPlot->setFixedSize(480,300);
 4 
 5     //blue line
 6     myPlot->addGraph();
 7     myPlot->graph(0)->setPen(QPen(Qt::blue));
 8 
 9     //xAxis
10     myPlot->axisRect()->setupFullAxesBox();
11 
12     myPlot->xAxis->setRange(1, 1, Qt::AlignRight);
13     myPlot->yAxis->setRange(30, 30, Qt::AlignRight);
14 
15     myPlot->xAxis->setLabel("I(A)");
16     myPlot->yAxis->setLabel("U(V)");
复制代码

2. 关于 buffer

  QCustomPlot 提供的几个 example 中,几乎都是用这两种给图表喂数据的方法:setData() 和 addData()。

  在数据比较少,或者是设备性能比较好时,这没什么问题。但是,大数据量、有限资源时,效率真的很让人崩溃。看了 QCumstomPlot 实现这两个函数的代码。居然,都是先申请一个新的buffer,把旧的 buffer 里内容和新数据一起拷贝到新 buffer !!!而且,buffer 是用 QMap 实现的! 所以,就是我们的数据在内存里拷来拷去。

  读了 API 文档,它其实提供了另一个接口,而且它在文档里推荐大家使用这个接口!!!看下面代码:

1     QCPDataMap *mData = myPlot->graph(0)->data();
2     mData->clear();

  data() 这个调用,返回了指向内部画图 buffer 的指针!然后,我们就可以在需要的时候,往 buffer 里面添加数据

复制代码
1 void addToDataBuffer(float x, float y)
2 {
3     QCPData newData;
4 
5     newData.key = x;
6     newData.value = y;
7 
8     mData->insert(x, newData);
9 }
复制代码

  QCPDataMap 是使用 QMAP 结构实现的一个字典,使用 x 作为字典的 key;字典的值 QCPData 是一个自带操作方法的对象,可以看做坐标横纵坐标的组合 (x,y)。

  所以,字典里添加元素,操作就是 insert 了;如果需要多个 x 对应一个 y,那就是字典的 key 可以对应多个值,可以使用 insertMulti() 往 buffer 里面添加数据。

  同样的,更新完数据,我们需要 replot() 一下。还有,每次画新的曲线之前,先 clear 一下 buffer 就好。

-------------------------------------------------------------------------------------------------------------疯哥线

  今天有个哥们跟我讲 QCustomPlot 2.0,这个方法不能用了。正好有空,就翻了一下 2.0 的代码,找打下面的方法发给他。我也还没试。而且这方法并没有在官方文档中提到。

复制代码
 1 void MainWindow::addNewData()
 2 {
 3     QSharedPointer< QCPGraphDataContainer > dataContainer;
 4     dataContainer = customplot->graph(0)->data();
 5 
 6     QVector<QCPGraphData> mData; //warning: it's a local var
 7 
 8     QCPGraphData newPoint; 
 9     newPoint.key = 123;
10     newPoint.value = 456;
11 
12     mData.append(newPoint);
13 
14     dataContainer->set(mData,true); //if the data has been sorted, set true
15 }
复制代码

  因为画图数据的核心,就是这里的 mData,它就是一个 QCPGraphData  类型的 Vector,所以,我们直接构建这样一个 Vector,把内部的替换掉即可。可惜这里不是指针,函数内实现方式是用我们提供的 mData 给内部 mData 赋值,也就是,还是要进行一次拷贝。当然,你也可以去改它的代码把这个指针给放出来。

-------------------------------------------------------------------------------------------------------------疯哥线

  边吃早饭又看了一下,直接把 mData 给拿出来用了,避开了这次赋值。真不知道作者为什么要搞这么复杂。第一个是示例,第二个是要修改 qcustomplot.h 的(因为 QVector< >不会自动排序,所以,使用这种方法,默认你已经按照key 的大小将数据放好了;没排序的话,你还是用上面那种方法吧):

复制代码
 1 void MainWindow::mDataDirect(QCustomPlot *customPlot)
 2 {
 3     demoName = "mData";
 4 
 5     customPlot->addGraph();
 6 
 7     QVector<QCPGraphData> *mData;
 8     mData = customPlot->graph(0)->data()->coreData();
 9     mData->clear();
10     QCPGraphData newPoint;
11     for (int i=0; i<101; ++i)
12     {
13         double tmp = i/50.0 - 1; 
14         newPoint.key = tmp;
15         newPoint.value = tmp * tmp;  // let's plot a quadratic function
16 
17         mData->append(newPoint);
18     }
19 
20     // give the axes some labels:
21     customPlot->xAxis->setLabel("x");
22     customPlot->yAxis->setLabel("y");
23     // set axes ranges, so we see all data:
24     customPlot->xAxis->setRange(-1, 1);
25     customPlot->yAxis->setRange(0, 1);
26 }
复制代码

  在 qcustomplot.h 中加一行

复制代码
1 // setters:
2   void setAutoSqueeze(bool enabled);
3 
4   // myMethod
5   QVector<DataType>* coreData() {return &mData;}
6 
7   // non-virtual methods:
8   void set(const QCPDataContainer<DataType> &data);
复制代码

3. 画图区域的背景色

  不要问我为什么,我是读代码发现的:

1     QBrush backRole;
2     backRole.setColor("skyblue");
3     backRole.setStyle(Qt::SolidPattern);
4     myPlot->setBackground(backRole);

  如果不加 SolidPattern,画出来的图是透明的。

下面摘自某个已经打不开的博客:

  QCustomPlot采用了大量的技术比如自适应采样和文本对象缓存为了减少replot的时间。然而一些特性比如半透明的填充,反锯齿和粗线条都可能导致低效率。如果你在你的程序中注意到了这些。这有一些提示关于如何跳高Replot的性能。
  大部分时间耗费在绘图函数上尤其是绘制高密度的图形和其他图。为了最大性能思考下面几点:
  使用Qt4.8.0及以上的版本,性能将会有双倍或者三倍的提升跟Qt4.7.4相比。然而QPainter被破坏了并且绘制精确像素的东西使用Qt>=4.8.0的版本是不可能的。因此它是性能和质量的权衡当转到Qt4.8.0时。QCustomPlot内部尝试解决这种严重的故障。
  为了增加响应速度在进行范围拖拽的期间,思考设置QCustomPlot::setNoAntialiasingOnDrag为true.
  在X11,避免本地缓慢的绘图系统,使用栅格通过应用 "-graphicssystem raster"作为命令行参数或者调用QApplication::setGraphicsSystem("raster") 在创建应用程序对象之前。
  在所有的操作系统中,使用OpenGL硬件加速通过提供 "-graphicssystem opengl"作为命令行参数或者调用QApplication::setGraphicsSystem("opengl")。如果OpenGL是可用的,这将略有减少抗锯齿的质量但是却增强了性能尤其是半透明的填充,抗锯齿和大量的QCustomPlot绘制表面。然而注意最大帧速率的可能被你的显示器的垂直同步频率约束因此对于简单的plot来说,OpenGL加速可能实现帧速率数值低于其他图形系统,因为他们不以垂直同步频率为限制。
  避免任何形式的α(透明度),特别是在填充。
  避免用宽度大于1的画笔画线。
  避免任何反锯齿,尤其是在曲线图中的线。
  避免重复设置完整的数据用QCPGraph::setData。使用QCPGraph::addData代替,如果大部分的数据点保持不变如在运行的测量。你可以访问并且操作存在的数据通过QCPGraph::data.
  设置setData的拷贝参数为false,因此只有一些点得到转移。
  尝试减少数据点的数量在可见的主演范围在给出的任意时刻,通过限制key的最大范围。QCustomPlot可以有效优化掉数以百万计的屏幕点。

4. 更新非 graph 的 plottable

  在 qcustomplot 中,graph、curve、bar 这些,都被称为 plottable。其中,针对 graph,qcustomplot 在其顶层有单独的方法操作,如上面例子中的 graph(0) 可以返回添加的第一个 graph。

  其他的几种 plottable 都没有单独的方法,都是共用方法。而且,该共用方法也使用 graph。

  下面是以 bar 为示例,对其数据进行更新,并重画图:

复制代码
 1     QVector<double> x(42), y(42);
 2 
 3     for(int i = 0; i < 42; i++)
 4     {
 5         x[i] = i;
 6         y[i] = ( harmonic_rms[i] * 100) / harmonic_total;
 7     }
 8 
 9     QCPBars *theBar = (QCPBars *)harmonicPlot->plottable();
10     theBar->setData(x,y);
11 
12     harmonicPlot->rescaleAxes();
13     harmonicPlot->yAxis->setRange(0, 105);
14     harmonicPlot->xAxis->setRange(0, 42);
15 
16     harmonicPlot->replot();
复制代码

  plottable(int index) 是一个重载函数,如果携带 index,那么返回第 index 个 plottable;如果不带 index,则返回最后一个。因为我这里只有一个 QCPBar,所以,直接不带参数就可以了。

转载:https://www.cnblogs.com/ybqjymy/p/17997375

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

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

相关文章

Windows实用小工具使用教程!OFGB专治 Windows 11 广告的神器+自动滚屏小工具!

软件获取点这里 实用小工具第一款:OFGB - Windows 11系统广告屏蔽工具 工具介绍 OFGB(“广告滚蛋”)是一款专为Windows 11量身打造的免费开源广告屏蔽工具。自从Windows系统更新后,系统广告越来越多——文件管理器…

八数码难题

果然是天才的灵光一现 #include <bits/stdc++.h> using namespace std; int dx[4]={1,-1,0,0}; int dy[4]={0,0,1,-1}; int bfs(string st) {map<string,int>m;queue<string>pq;m[st]=0;pq.push(st)…

趣睡科技与强脑合作:AI算法赋能睡眠健康

在《2025年中国睡眠健康调查报告》中,一组数据揭示了当代人的普遍困境:近半数18岁及以上人群正遭受睡眠困扰。当无数人在深夜辗转反侧,睡眠质量已成为影响日常生活和健康的核心问题之一。在这一背景下,趣睡科技与强…

【转载】Qt QCustomPlot 使用教程

(一)——安装与配置 1、下载去 Qt Plotting Widget QCustomPlot - Download下载需要版本的QCustomPlot的压缩包QCustomPlot.tar.gz,下载解压后会得到qcustomplot的.cpp与.h文件,这两个文件是我们需要的。 2、添加到…

2025年11月营销智能体选择指南:权威榜单与用户评价深度分析

在数字化转型加速的今天,企业营销面临数据孤岛、决策效率低、成本控制难等共性挑战。作为营销决策者或业务负责人,您可能需要通过智能技术优化广告投放、客户运营或内容策略,但市场上工具繁多、功能参差,如何选择适…

2025年11月营销智能体推荐榜单:主流平台综合对比与选择指南

在数字化转型浪潮中,企业营销面临数据孤岛、决策效率低下、用户触达精准度不足等共性挑战。营销智能体作为人工智能技术在营销领域的具体应用,通过数据驱动与自动化决策,正逐步成为企业提升营销效能的关键工具。根据…

2025年11月营销智能体推荐榜单:主流平台列表与权威选择指南

在数字化转型浪潮中,企业营销面临着数据孤岛、决策效率低下、用户触达不精准等普遍痛点。营销智能体作为人工智能技术在营销领域的重要应用,正逐步成为企业提升营销效果的关键工具。根据行业报告显示,超过60%的大型…

2025年11月营销智能体推荐榜单:五大主流平台深度对比与选择指南

在当前数字化营销快速迭代的背景下,企业对于智能化决策工具的需求日益显著。作为营销决策者或企业管理者,您可能正在寻找能够有效整合数据、优化营销流程并提升转化效率的智能解决方案。营销智能体作为一种融合人工智…

HarmonyOS 帧动画 animator

就是类似播放电影一样,一帧一帧的进行播放,相对于属性动画,其每一帧,我们都可以进行设置相关的属性值,并且具有暂停播放,继续播放的优点,而且还具备事件的实时响应,需要说明的是,在性能上是远远不如属性动画的…

2025年11月副业平台推荐榜:五大平台深度对比与选择指南

随着经济环境变化与个人发展需求多元化,越来越多的人开始寻求副业以增加收入来源或探索职业可能性。选择副业平台的用户可能包括职场新人希望提升技能并赚取额外收入,全职父母寻求灵活的工作时间,或创业者寻找低风险…

HarmonyOS 关键帧动画 keyframeAnimateTo

使用UI上下文API中的.keyframeAnimateTo()方法创建关键帧动画,其中传两个参数,第一个参 数是个对象,此对象有三个参数delay、iterations、onFinish;第二个参数是数组,其中是一个个对象,每个对象都是一个关键帧 基础使…

HarmonyOS 开发应用沉浸式效果

开发应用沉浸式效果 概述 典型应用全屏窗口UI元素包括状态栏、应用界面和底部导航条,其中状态栏和导航条,通常在沉浸式布局下称为避让区;避让区之外的区域称为安全区。开发应用沉浸式效果主要指通过调整状态栏、应用…

HarmonyOS 属性动画.animation()

基础使用 - 1. 属性动画响应式(确定谁加动画) @State scaleX: number = 1 @State scaleY: number = 1Text().width(50).height(50).backgroundColor(Color.Red).scale({ x: this.scaleX, y: this.scaleY })- 2. 触发…

HarmonyOS游戏开发入门:用ArkTS打造经典五子棋

​ 引言 五子棋是一款经典的策略游戏,规则简单但乐趣无穷。本文将带你使用 HarmonyOS 的 ArkUI 框架,以组件化的思想快速实现一个双人对战的五子棋游戏。我们将逻辑与 UI 分离,打造一个结构清晰、易于维护的应用。 …

详细介绍:【论文阅读】AAAI 2025 | 面向精确分割式联邦学习的多模型聚合与知识重放

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Harmony ArkTS 并发编程全攻略:从基础概念到多线程实战,彻底搞懂性能优化

计算机基础概念在日常的生活或工作中,计算机几乎无处不在,特别是对于我们高级开发攻城狮来说、每天都要使用、来开发各种各样的程序,所以为了能够写出更好的程序、了解计算机基础知识是必要的,接下来就让我们来聊聊…

HarmonyOS文件操作进阶:上传/下载/解压全场景实战(含封装工具类)

​ 一、文件上传:从基础到企业级方案 文件上传是鸿蒙应用开发的核心场景(如头像上传、附件提交、图片分享),鸿蒙基于沙箱安全机制,要求上传文件必须先存入应用沙箱目录(cacheDir),再通过系统 API 提交。以下是…

HarmonyOS 文件操作不用愁:沙箱机制解析 + 可抄代码,零基础上手

一、应用沙箱:鸿蒙应用的 “安全文件柜”​核心简介​应用沙箱是鸿蒙系统为保障数据安全设计的隔离存储机制,每个应用都会获得专属的 “沙箱目录”,实现三大核心目标:​ 数据隔离:应用仅能访问自身文件和少量必需…

HarmonyOS ArkTS 状态管理 V2 全解析:新装饰器 + 实战示例 + 面试题(简述方便新手快速了解使用)

​ 鸿蒙 ArkTS 状态管理 V2 带来了一系列全新装饰器,不仅解决了 V1 版本中装饰器混淆、观测能力有限等问题,还强化了语义化和性能优化。本文将详细拆解@Local、@Param、@ObservedV2等核心装饰器,结合实战代码和对比…

2025最新机械密封件制造厂家实力榜!国内顶尖机械密封品牌权威发布,技术与服务双重保障,机械密封/机械密封件/釜用机械密封/双端面机械密封/机械密封维修品质与专业深度剖析,选择指南

随着工业设备对密封性能要求的不断提高,机械密封作为关键零部件,其质量与可靠性直接关系到生产安全与效率。本榜单基于技术研发实力、产品应用范围、服务响应速度三大维度,结合行业权威数据及用户反馈,对2025年国内…