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);
  • 16
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:清华大学的操作系统视频课讲的比较精炼,涉及到的内容没有那么细,《操作系统 - 哈工大》李治军老师授课的视频课程相对就会比较细节,老师会用 Linux 内核代码的角度带你进一步理解操作系统,也会用生活小例子帮助你理解。 引用\[2\]:在操作系统中,设置当前工作目录的主要目的是加快文件检索速度。\[2\]在磁盘上,最容易导致存储碎片发生的物理文件结构是顺序存放。\[2\]操作系统引入中断和并行硬件机制来实现CPU和设备的并行。\[2\]操作系统的基本特征是并发、共享、虚拟、多道。\[2\]虚拟存储用到了程序的分段原理。\[2\]对记录式文件,操作系统为用户存取文件信息的最小单位是记录。\[2\]将逻辑转换为物理地址称为地址映射。\[2\] 引用\[3\]:在选择修建路线时,可以采用最短路径算法或最小生成树算法。\[3\]关于电报字符的哈夫曼编码,可以根据字符的出现频率来确定编码,频率越高的字符编码越短。\[3\]冒泡排序的关键字移动方向和排序顺序相反的情况可能是由于初始序列已经是有序的,快速排序不会出现这种情况。\[3\] 问题: 数据结构与操作系统和数据结构的区别 回答: 数据结构是计算机科学中研究数据组织和存储方式的一门学科,它关注如何组织和管理数据以便有效地访问和操作。数据结构是一种抽象的概念,它可以用来描述数据的逻辑结构和物理结构。操作系统是计算机系统中的一个重要组成部分,它负责管理和控制计算机硬件和软件资源,为用户和应用程序提供服务。操作系统涉及到进程管理、内存管理、文件系统、设备管理等方面的内容。数据结构和操作系统是两个不同的领域,但在实际应用中,数据结构和操作系统经常会相互影响和关联。例如,操作系统需要使用数据结构来管理进程和文件系统中的数据。同时,数据结构的设计和选择也会受到操作系统的限制和要求的影响。因此,数据结构和操作系统是相互关联的,但它们是两个独立的学科。 #### 引用[.reference_title] - *1* [数据结构,计算机网络,数据库,计算机组成原理,操作系统有哪些好的网课值得推荐?](https://blog.csdn.net/qq_34827674/article/details/118254836)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [2022 年天津理工大学研究生招生考试 808 数据结构与操作系统](https://blog.csdn.net/m0_47776000/article/details/126493673)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值