qcustomplot实时滚动显示,内存释放删除数据

之前一篇介绍了如何滚动数据和时间轴:http://labisart.com/blog/index.php/Home/Index/article/aid/200

但是呢,一直adddata会导致内存开销增大,在csdn上那些叼毛也没说怎么删除数据好一点。

长时间运行是不可接受的,这就涉及到如何定时删除数据释放内存的问题。

实际测试,

mGraph1->data()->clear();    
mGraph2->data()->clear();
// 以及:
//ui->widCapGraphics->clearGraphs();
//ui->widCapGraphics->clearPlottables();
//ui->widCapGraphics->plotLayout()->clear();

这2种方式还是不能很好的控制内存。而且一下clear了导致会断线,很挫。

removebefore()也不太好使!(可能没用对?)

仔细看文档有一个setData函数,我们自定义两个qvector<double>变量传进去就可以自己控制内存开销了,此时可以只滚动曲线,不滚动x坐标。

具体思路是:

1、key.append(0~99),放100个数

2、serial.append(全部初始化为0);

3、更新时,serial.removefirst(),然后serial.append(新数据)。再次customplot->setData(key,serial)就可以了!


现在有个问题,x以个数显示没问题了,就用key.append(0~99).

那么如果x轴用时间怎么来赋值这个key呢?其实只要知道,x轴以时间为单位时,以秒为基本单位赋值就好了,具体如下:

初始化:

    // 设置x轴为时间.%z    
    QSharedPointer<QCPAxisTickerTime> timeTicker(new QCPAxisTickerTime);
    timeTicker->setTimeFormat("%h:%m:%s");
    ui->widCapGraphics->xAxis->setTicker(timeTicker);
    
    // 使用外部数据,提前10秒初始化,100毫秒刷新一次,共100个数据
    int64_t now = QTime::currentTime().msecsSinceStartOfDay();

    now -= 10*1000;
    for(int i=0;i<100;i++){
        m_key.append((now + i*100)/1000.0);
        //m_key.append(i); // ok了
        m_sdata.append(sin(0.6f*i));
        m_sdata2.append(cos(0.25f*i));
    }
    mGraph1->setData(m_key,m_sdata);
    mGraph2->setData(m_key,m_sdata2);

定时刷新:

    // 改变数据    
    m_key.removeFirst();
    m_key.append(nowtime/1000.0);

    m_sdata.removeFirst();
    m_sdata.append(sin(0.6f*m_cnt));

    m_sdata2.removeFirst();
    m_sdata2.append(cos(0.25f*m_cnt));

    mGraph1->setData(m_key,m_sdata,true);
    mGraph2->setData(m_key,m_sdata2,true);


这个有点像qcharts的replace函数,不过对比了一下,qcharts的普通方法cpu占用率太高了,比qcustomplot高一倍,用replace勉强能达到qcustomplot的标准,所以还是用qcustomplot。

实例:

LYJ博客

单独下载查看:

20210213233717957.gif


本文为3YL原创,转载无需联系,但请注明来自labisart.com。

原创文章不易,如果觉得有帮助,可打赏或点击右侧广告支持:

查看打赏记录

发表评论请遵守党国法律!后台审核后方可显示!
  • 最新评论
  • 总共2条评论

yefeng:线条多,数据量大情况下,我发现这个库运行时间长了会奔溃getlines里面取可见区域位置时,内存已被释放。

2022-09-21 09:26:35 回复

  • 3YL 回复 yefeng:会不会哪里没有配好?我测试过没这个问题
  • 2022-09-27 16:11:44 回复
  • yefeng 回复 3YL:我用的很简单,就adddata,replot,我数据量比较大,64条线,每秒钟有几万个点,replot里面有个一次性的定时器,定时器执行的时候会获取可见区域点集,取出来有时候会出现qvector数据已被释放,添加过程中他内部会自动调整内存,所以有时候会出现这种情况,但目前不知道怎么解决,您对这个库内部有研究吗。
  • 2022-10-07 00:27:40 回复
  • 3YL 回复 yefeng:你可以这样考虑,10多万个点每秒,眼睛不可能分辨出来,直接抽取显示,效果差不了多少
  • 2022-10-08 19:29:57 回复
  • yefeng 回复 3YL:我觉得您说的这种降采样方式是可行的,我现在已经在尝试这种方式,还有待验证,项目交叉的原因可能需要一段时间,后期验证结果我也会在这回复,感谢您的回复,谢谢大佬
  • 2022-10-09 09:54:30 回复

Marcellus:我这边个人理解最好使用QCPGraph类的QCPGraph::setData(QSharedPointer<QCPGraphDataContainer> data);在外部实现一个DataManager类,管理QSharedPointer<QCPGraphDataContainer>data_buffer数据。当data_buffer数据长度超过多少秒后,就可以主动清除一次。也方便实现多线程数据输入。不过我觉得qcustomplot最坑的是卡顿问题。我这边实现的1ms的实时数据采样, 20ms的QCusomplot的updatePlot()定时刷新。setScatterStyle千万别是ssDot,还有最好不要设置legend可选择,这个功能打开后,在实时刷新下,选中波形后就可能卡顿了。不过我这边测试如果是20ms的实时数据采样,貌似也不会卡。

2021-09-27 15:32:33 回复

  • Blog v1.1© 2024 labisart.com 版权所有 | 联系:labartwork@163.com