用qcustomplot类画实时曲线replot()速度跟不上硬件采集数据的速度怎么办

sinat_35774390 2016-08-06 08:33:48
我现在在做一个界面,实时显示从硬件上采集得到的数据,画成曲线或者散点。最近在论坛中朋友的帮助下有了一点思路:创建一个子线程,在子线程中采集硬件数据,在主线程中用qcustomplot画图,子线程中发送数据信号,触发主线程的槽函数,在主线程的槽函数中画图。但是现在又出现了一个问题,就是在我做的这个界面上实时画图的速度跟不上硬件采集数据的速度。因为我的硬件有一个LCD屏幕,在这个屏幕上已经实现了实时画数据。两个一对比就发现qt界面上画图速度跟不上LCD上的画图速度。我的硬件采集数据的速度大概是每15ms采集一个点,界面上一次画127个点。而且感觉我的画图部分的代码也不多啊。。请问该怎样处理才能提高qcustomplot的画图速度?
下面是我的简略的代码,布局的代码没写,代码写得乱,请各位大神将就着看。。
[code=c++]
Widget.h
class Widget : public QWidget
{
Q_OBJECT

public:
explicit Widget(QWidget *parent = 0);
~Widget();

public slots:
void readData(unsigned int ledinx,int num);

private:
Ui::Widget *ui;
QCustomPlot *myplot;
Thread *myThread;
double key;
double data;
void realtimeDataSlot();
}


Widget.cpp
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui -> setupUi(this);
key = 0;
data = 0;

myplot = new QCustomPlot;
myplot -> addGraph(0);

myThread = new Thread;
connect(myThread,SIGNAL(UpdateSignal(unsigned int ,int)),this,SLOT(readData(unsigned int,int)));

myThread -> start();
}

void Widget::readData(unsigned int ledinx,int num)
{
key = ledinx;
data = num;
realtimeDataSlot();
}

void Widget::realtimeDataSlot()
{
myplot -> graph(0) ->removeData(key);
myplot -> graph(0) -> addData(key,data);

myplot -> replot();
}
[/code]
...全文
6478 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
TianCaiTang 2020-04-15
  • 打赏
  • 举报
回复
楼主,能否分享一下代码,我是名Qt小白,现在想把AD采集到的信号实时显示出来,所以想参考你的代码学习一下。邮箱:1005605205@qq.com 不胜感激!
m0_46171324 2020-03-23
  • 打赏
  • 举报
回复
楼主,你好,我最近也在学习AD采集的这个,能方便分享一下源码吗,万分感谢。邮箱2263938707@qq.com
LittleFly4398 2018-08-22
  • 打赏
  • 举报
回复
嗯,感觉楼主调用 replot(QCustomPlot::rpQueuedReplot) 的方法也是可行的。读了一下说明,感觉和QWidget的repaint()与update()的区别挺像的。
另外说一下我的做法,我的数据采集和绘图是分离的,因为数据采集和绘图是两个不同的功能。我之前以及目前都是通过QTimer的响应槽函数来replot()的,因为QTimer的槽函数不会被新的timeout打断,而且经过测试,QTimer触发时间小于槽函数运行时间时,并不会导致槽函数响应次数累积。采用QTimer触发绘图的方法,绘图的刷新率是动态变化的,而且性能好一点平台的刷新率会比较高(不会超过QTimer设定的触发周期对应的刷新率)。
然后换一个角度说一下replot时间要求的问题,目前大部分的显示器的刷新率都是60hz,因此你replot()的刷新率达到60就差不多了,再上去也看不出什么效果。
qq_39657476 2018-07-30
  • 打赏
  • 举报
回复
新版本更新后没那么麻烦了,可以看一下官方给出的帮助文件
void QCustomPlot::replot ( QCustomPlot::RefreshPriority refreshPriority = QCustomPlot::rpRefreshHint)
Causes a complete replot into the internal paint buffer(s). Finally, the widget surface is refreshed with the new buffer contents. This is the method that must be called to make changes to the plot, e.g. on the axis ranges or data points of graphs, visible.

The parameter refreshPriority can be used to fine-tune the timing of the replot. For example if your application calls replot very quickly in succession (e.g. multiple independent functions change some aspects of the plot and each wants to make sure the change gets replotted), it is advisable to set refreshPriority to QCustomPlot::rpQueuedReplot. This way, the actual replotting is deferred to the next event loop iteration. Multiple successive calls of replot with this priority will only cause a single replot, avoiding redundant replots and improving performance.

Under a few circumstances, QCustomPlot causes a replot by itself. Those are resize events of the QCustomPlot widget and user interactions (object selection and range dragging/zooming).

Before the replot happens, the signal beforeReplot is emitted. After the replot, afterReplot is emitted. It is safe to mutually connect the replot slot with any of those two signals on two QCustomPlots to make them replot synchronously, it won't cause an infinite recursion.

If a layer is in mode QCPLayer::lmBuffered (QCPLayer::setMode), it is also possible to replot only that specific layer via QCPLayer::replot. See the documentation there for details.
也就是说,把重画的频率高的部分的replot();改成replot(QCustomPlot::rpQueuedReplot);就可以了
sawyer24 2018-04-10
  • 打赏
  • 举报
回复
请问楼主:connect(myThread,SIGNAL(UpdateSignal(unsigned int ,int)),this,SLOT(readData(unsigned int,int))); 中的子线程的UpdateSignal(unsigned int ,int)信号你是如何定义的?
sawyer24 2018-04-02
  • 打赏
  • 举报
回复
楼主,能否分享一下代码,我是名Qt小白,现在想把AD采集到的信号实时显示出来,所以想参考你的代码学习一下。邮箱:2210605591@qq.com 不胜感激!
个何必 2017-12-14
  • 打赏
  • 举报
回复
谢谢楼主
KeKiKeKi 2017-02-19
  • 打赏
  • 举报
回复
其实从你硬件传回数据也是需要耗时的,LCD屏幕和上位机不同步也正常把
sinat_35774390 2016-08-09
  • 打赏
  • 举报
回复 3
谢谢各位朋友了!最终我是这样解决的,把realtimeDataSlot()函数中的addData和replot分离,写在两个函数里,然后每采集一个点执行一次addData,但是每采集四个点才执行一次replot,这样把重画的频率降低,replot的速度就能跟上硬件采集数据的速度了。虽然并没有真正做到实时显示数据,但是因为硬件采集数据的速度太快了,所以隔4个点再replot看起来也像是实时显示一样。

16,239

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧