QCustomPlot 曲线数据结构与存取

对了,我开通了微信公众号,计划是两边会同步更新,并逐步的会将博客上的文章同步至公众号中。感兴趣的朋友可以搜索“里先森sements”来关注,欢迎来玩~!


通常,我们对QCustomPlot中的曲线数据无外乎增、删、改、查这几种操作。然而对于初次或者接触QCustomPlot时间不长的用户来说,其提供的曲线数据操作接口可能让人有些摸不着头脑。因此,在这里记录本人对QCustomPlot曲线数据操作的一些理解和经验,以供各位参考。这里我们仅讨论常用的QCPGraph数据,QCPCurve不在讨论范围内。

对于大部分用户来说,使用QCustomPlot是为了展示序列化的曲线数据,即每一个键(key,x轴坐标)仅对应一个值(value,y轴坐标),并且这些数据往往是已经按照顺序排列好的。然而,QCustomPlot为了兼容多种应用(如单个键对应多个值),其内部的设计要更为复杂。下面的例子展示了单个键对应多个值的情况

ui->CP_Plot->addGraph();
auto graph =ui->CP_Plot->graph();
graph->addData(1,1.1);
graph->addData(1,2.1);
graph->addData(2,1.2);
graph->addData(2,2.2);
graph->addData(3,3.5);

在这里插入图片描述

为了实现对曲线数据的安全高效管理,QCustomPlot实现了一个数据存储容器:QCPDataContainer。这里T是模板。我们常见的便是 QCPDataContainer,你可以通过下面的方法来获取它

//获取新建立图层的数据存储容器
ui->CP_Plot->addGraph();		
QCPDataContainer<QCPGraphData>* pContainer = ui->CP_Plot->graph()->data().data();

注意, g r a p h ( ) − > d a t a ( ) graph()->data() graph()>data() 返回的是 QSharedPointer 智能指针,你需要调用其 d a t a ( ) data() data() 方法才能获取 Q C P D a t a C o n t a i n e r < Q C P G r a p h D a t a > ∗ QCPDataContainer<QCPGraphData>* QCPDataContainer<QCPGraphData>。作为数据存储容器,QCPDataContainer 实现了很多常见的数据操作,部分操作可以直接通过调用方法执行,而部分则需要使用其内部的数据迭代器(iterator)。

绝大部分情况下,用户希望对已知键位置的数据点进行操作。然而正如前文所述,由于QCustomPlot的数据存储容器需要考虑一个键对应多个值的情况,因此你所持有的键并不能完全确定你所需要定位的点(例如前例中的点(1,2.1)与点(1,1.1))。在查看 QCustomPlot 的帮助文档时,你也会发现部分方法需要提供的参数并非键(key)而是数据下标(index)。这是由于 QCPDataContainer 内的数据都是以顺序方式存储的,索引每个数据点的并非键,而是其顺序下标。在 QCPDataContainer 的帮助文档中你可以看到下面的表述:

The data is stored in a sorted fashion, which allows very quick lookups by the sorted key as well as retrieval of ranges (see findBegin, findEnd, keyRange) using binary search. The container uses a preallocation and a postallocation scheme, such that appending and prepending data (with respect to the sort key) is very fast and minimizes reallocations. If data is added which needs to be inserted between existing keys, the merge usually can be done quickly too, using the fact that existing data is always sorted.

因此,你可以理解为我们在绘图坐标系上使用到的键(key,x轴坐标)与值(value,y轴坐标)都不过是数据存储容器中某个元素内部的值而已,真正要找到这个元素,要么通过元素下标,要么枚举查找。理解了这一点,便能把握整体思路与方向。下面我们以常见的,已知数据点键(key),介绍几种对曲线中对应数据点进行操作的方法。

3.2.1 数据的增加与删除

数据的增加与删除比较简单,QCPDataContainer 已经给出了对应的方法,按需调用即可:

/*** 增加点(4,4.1) ***/
//方法1,使用 QCPDataContainer 的 add() 方法
ui->CP_Plot->graph()->data()->add(QCPGraphData(4,4.1));		//QSharedPoint指针
//方法2,使用 QCPGraph 的 addData() 方法
ui->CP_Plot->graph()->addData(4,4.1);

/*** 删除点 ***/
ui->CP_Plot->graph()->data()->remove(4);	//删除 键key==4的所有点
ui->CP_Plot->graph()->data()->clear();		//删除曲线内所有数据点

其余类似方法(如 removeBefore)可参考相关文档。注意,QCPDataContainer 的 r e m o v e ( d o u b l e s o r t K e y ) remove(double sortKey) remove(doublesortKey) 方法会移除所有键相同的点,如若仅需移除同键的部分点,需结合枚举查值的方式进行。

3.2.2 数据值查找

在查看某键对应的数据点的值时,需要用到数据存储容器的迭代器与 QCPDataContainer 的方法 f i n d B e g i n ( ) findBegin() findBegin()。该方法在 QCustomPlot 内部实质上也是枚举所有的数据点,逐个比对其键的值,而后根据参数返回用户需求的数据点的迭代器。

ui->CP_Plot->addGraph();

/*** 新增数据点 ***/
auto graph =ui->CP_Plot->graph();
graph->addData(1,1.1);
graph->addData(1,2.1);
graph->addData(2,1.2);
graph->addData(2,2.2);
graph->addData(3,3.1);

/*** 使用迭代器查看数据点值 ***/
//获取key为1的数据点迭代器,该例中其指向第一个数据点(1,1.1)
QCPDataContainer<QCPGraphData>::const_iterator it = graph->data()->findBegin(1,false);
//枚举所有数据点直至QCPDataContainer末尾
for(;it != graph->data()->constEnd(); it++)
{
    qDebug()<<"it->sortKey(): "<<it->sortKey();
    qDebug()<<"it->mainKey()/it->key: "<<it->mainKey();
    qDebug()<<"it->mainValue()/it->value: "<<it->mainValue()<<"\n";
}

f i n d B e g i n ( ) findBegin() findBegin() 方法的 expandedRange 参数可以限定搜索方法。具体请参照 QCustomPlot 说明文档

If expandedRange is true, the data point just below sortKey will be considered, otherwise the one just above.
This can be used in conjunction with findEnd to iterate over data points within a given key range, including or excluding the bounding data points that are just beyond the specified range.
If expandedRange is true but there are no data points below sortKey, constBegin is returned.

3.2.3 数据值修改

修改数据点的值时同样需要使用迭代器,但这里使用的迭代器是非常量迭代器QCPDataContainer::iterator,该迭代器允许我们直接修改元素的相关变量,如键(key)与值(value)。

/*
 *  修改已有数据点值
 *  例 将第5个数据点的值从3修改为3.5
 */
QCPDataContainer<QCPGraphData>::iterator mit;
//方法1 直接定位,需知道数据点顺序
mit = graph->data()->begin() + 4;
mit->value = 3.5;

//方法2 枚举key值查找
mit = graph->data()->begin();
for(; mit != graph->data()->end(); mit++)
{
    if(3 == mit->key)
        break;
}
mit->value = 3.5;

//方法3 remove and add
it = graph->data()->findBegin(3,false);
QCPGraphData newData(it->key,3.5);
graph->data()->remove(3);               //移除key为3的所有数据点
graph->data()->add(newData);

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

xshell配置隧道转移规则

钢铁知识库&#xff0c;一个学习python爬虫、数据分析的知识库。人生苦短&#xff0c;快用python。 xshell是什么 通俗点说就是一款强大ssh远程软件&#xff0c;可以方便运维人员对服务器进行管理操作&#xff0c;功能很多朋友们自行探索&#xff0c;今天只聊其中一个功能点那…

【RHCSA服务搭建实验】之apache

虚拟web主机类型 一、基于端口 1.vim /etc/httpd/conf.d/vhost2.conf ---- — 改变http服务默认访问路径 <directory /testweb1>allowoverride none 表示不允许覆盖其他配置require all granted 表示允许所有请求 </directory> <virtualhost 0.0.0.0:…

分布式系统中为什么需要使用消息队列

本文转载自 linkedkeeper.com 消息队列已经逐渐成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能&#xff0c;成为异步RPC的主要手段之一。 当今市面上有很多主流的消息中间件&#xff0c;如老牌的ActiveMQ、RabbitMQ&#…

【Docker】使用Docker安装Nginx及部署前后端分离项目应用

一、Nginx介绍 Nginx是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务。它是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.ru站点开发的&#xff0c;公开版本1.19.6发布于2020年12月15日。其将源代码以类BSD许可证的形式发布&#xff0c;因它…

RLC如何通过改变频率实现输出稳压

当开关频率工作在容性区域时&#xff0c;容抗抵消完感抗还有剩余&#xff0c;所以容抗感抗可以近似为一个容抗Cr,但加上频率的改变&#xff0c;容抗又可以近似为一个可调电阻 那又改如何控制频率&#xff0c;保持输出稳压&#xff1f; 当输入与输出电压不变时&#xff0c;Rac变…

尝试解决githubclone失败问题

BV1qV4y1m7PB 根据这个视频 似乎是我的linux的github似乎下好了 我没有配置好 比如我的ssh-key 现在根据视频试试 首先需要跳转到ssh的文件夹&#xff1a; cd ~/.ssh 然后生成一个ssh-key&#xff1a; ssh-keygen -t rsa -C "<github资料里的邮箱>" 然后…

Python(18)--文件输入/输出 Ⅱ

​ 大家好&#xff01;我是码银&#x1f970; 欢迎关注&#x1f970;&#xff1a; CSDN&#xff1a;码银 公众号&#xff1a;码银学编程 前言 前一篇文章&#xff08;python(17)–文件的输入/输出-CSDN博客&#xff09;介绍了如何操作文本文件和二进制文件&#xff0c;以及对应…

跨站点请求伪造攻击 - Cross Site Request Forgery (CSRF)

什么是CSRF 最好理解CSRF攻击的方式是看一个具体的例子。 假设你的银行网站提供一个表单,允许当前登录用户将钱转账到另一个银行账户。例如,转账表单可能如下所示: <form method="post"action="/transfer"> <

SpringBoot 更新业务场景下,如何区分null是清空属性值 还是null为vo属性默认值?

先看歧义现象 值为null 未传递此属性 所以此时如何区分null 时传递进来的的null&#xff0c;还是属性的默认值null? 引入方案 引入过滤器&#xff0c;中间截获requestBodyData并保存到HttpServletRequest&#xff0c;业务层从HttpServletRequest 获取到requestBodyData辅…

PCIe 5.0硬件

一、PCIe 5.0概述 (1)什么是PCIe 5.0 第五代快速周边组件互连称为PCI Express 5.0(Peripheral Component Interconnect Express 5.0),也称为第五代PCIe、PCIe 5、PCI v5或简称为PCIe 5.0。PCIe技术于2003年首次推出,现已成为使用点对点访问总线将高速组件连接到主板的标准接…

基于springboot的一个IT人才招聘网站系统源码+数据库+部署文档,公司可以发布岗位需求,求职者查找岗位并递交简历等

介绍 实现一个IT人才招聘系统&#xff0c;公司可以发布岗位需求&#xff0c;求职者查找岗位并递交简历等 启动 1. 主要技术版本 技术名称版本SpringBoot2.5.0MySQL8.0Redis6.2.0 2. 本地启动部署 2.1 数据库数据源部署 src/main/resources/application.yaml 配置文件&am…

Camera理论知识和基本原理(1)

1. 前言 本篇文章为Camera系列文章的第一篇&#xff0c;主要阐述Camera摄像头的基础理论知识&#xff0c;解决Camera硬件或Camera软件开发的一些困惑。该系列文章主要围绕Android操作系统进行&#xff0c;并涉及Android系统上Camera的协议、实现和应用。 2. Basic Concepts …

Java SE入门及基础(24)

目录 方法带参&#xff08;续第23篇文章&#xff09; 3. 对象数组 案例场景 练习 4. 引用数据类型作为方法的参数 案例场景 分析 代码实现 5. 数组作为方法的参数 案例场景 Java SE文章参考:Java SE入门及基础知识合集-CSDN博客 方法带参&#xff08;续第23篇文章&am…

Atlas元数据处理框架:让你的大数据应用更高效、更稳定!

介绍&#xff1a;Apache Atlas是一套开源的元数据管理和治理产品&#xff0c;由Apache软件基金会托管。它广泛应用于大数据领域&#xff0c;帮助企业管理数据资产&#xff0c;分类和治理这些资产&#xff0c;并为数据分析和数据治理提供高质量的元数据信息。 随着企业业务量的增…

k8s节点RouteCreated为false

出现该情况后&#xff0c;一般是初始化节点失败。因此&#xff0c;需要把节点从集群中移除&#xff0c;再加入到集群中&#xff0c;即可解决。 通常出现这个状况后&#xff0c;该节点上是没有被分配pod ip的&#xff0c;可以通过命令查看&#xff1a; # 发现没有PodCIDR、PodC…

Redis(五)

1、布隆过滤 1.1、简介 由一个初值都为零的bit数组和多个哈希函数构成&#xff0c;可以用来快速判断集合中是否存在某个元素&#xff0c;减少占用内存&#xff0c;不保存数据信息&#xff0c;只是在内存中做出一个标记。 它实际上是一个很长的二进制数组(00000000)一系列随机h…

【JavaEE Spring】SpringBoot 日志

SpringBoot 日志 1. 日志概述2. 日志使用2.1 打印⽇志2.1.1 在程序中得到⽇志对象2.1.2 使⽤⽇志对象打印⽇志 2.2 ⽇志框架介绍2.2.1 ⻔⾯模式(外观模式)2.2.2 SLF4J 框架介绍 2.3 ⽇志格式的说明2.4 ⽇志级别2.4.1 ⽇志级别的分类2.4.2 ⽇志级别的使⽤ 2.5 ⽇志配置2.5.1 配置…

Qt打包成为exe遇到的问题及其解决方法

Qt打包成为exe遇到的问题及其解决方法 文章目录 Qt打包成为exe遇到的问题及其解决方法0. 前言1. 使用Release编译工程2. 利用windeployqt工具来找出和复制依赖项3. 解决 Qt Location /Qt Positioning is not installed4. 利用Enigma virtual box打包 .exe程序5. dependency wal…

sfml使用opengl着色器实现2d水面波浪

SFML中使用GLSL着色器来绘制水波。 效果 代码 #include <SFML/Graphics.hpp> #include <iostream>int main() {const int WIDTH = 800;

Mysql 编译安装部署

Mysql 编译安装部署 环境&#xff1a; 172.20.26.198&#xff08;Centos7.6&#xff09; 源码安装Mysql-5.7 大概步骤如下&#xff1a; 1、上传mysql-5.7.28.tar.gz 、boost_1_59_0.tar 到/usr/src 目录下 2、安装依赖 3、cmake 4、make && make install 5、…