Qt:实现“类似示波器”的实时绘图的最佳方式

时间:2010-10-03 03:19:47

标签: c++ user-interface qt

我正在研究用于Qt的Gui-Module,以基于Qwt绘制数字示波器中的实时测量结果。到目前为止,一切都运行得很好,但也许还有一些功能需要补充; - )

当数据在QVectors中按列存储时,以及一个单独的QObject中的一个全局timeReference QVector。因此,可以逐行丢弃数据,以便仅将Meusurement保持到某个过去。所有QVectors总是具有相同的长度。然后,可以在QwtPlot中按时间正确地绘制完整数据。

我想更多地封装数据存储,以便更加独立于测量。因此,为每个测量添加一个单独的时间坐标列表并将它们放在一个单独的QObject中是很好的,它接受和传递数据。然后会有10或20个这样的QObject,每个数据通道一个,由QwtPlot上面的QObject单独绘制。

现在,数据可以是动态的 - 无论外部是否可以看到数据之间如何存储,更改或丢弃。

我的问题是:这很聪明吗? 20或30个QObjects包含每10000个测量值,10000个时间值,加上一个相似大小的单独存储区域(动态填充),其中一个子集ob数据用于绘图...?将QObject中的每个测量值作为信号接收是否合理,在1kHz左右发射?信号/插槽部分来自于稍后将每个OBject作为QThread的想法,并实现实时滤波,如数据上的低通或FFT - 因此,信号/插槽连接可以方便地控制输出。多线程环境?

如何在我的OBjects中有效存储数据?我正在考虑两个QList,一个用于时间,一个用于珍贵数据。然后动态分配两个普通的双数组用于动态访问,其指针与长度一起放在结构中并由accessData(pastTime)方法返回。动态存储器充满timeVal /测量组合,从“now”到过去的某个点,可由信号设置。在QObject中由互斥体保护的所有东西都很脆弱。

当丢弃旧值时,必须从头开始搜索QList,以获得足够年轻的第一个值,保留在该索引之前的那个值。由于其upperBound()函数,QMap是否更智能?我认为隐藏的开销不值得。

如何能够很好地,有效地解决这个问题或者没有任何麻烦?我应该知道的特殊Qt功能?或者甚至是那里的免费解决方案?无论如何,这个基本问题的文字很多......感谢您在这里阅读; - )

提前致谢

马文

edith:在stijns评论之后做了一些论证清理。

2 个答案:

答案 0 :(得分:6)

photo_tom的答案几乎总结了:我远离QObjects来实现数据处理和处理。

  • 如果您决定使用除Qt以外的其他东西,那么您将很难重构代码。像QList和QVector这样的类可以被STL对应物替换而没有太多问题,但信号/插槽部分是其他的。
  • 任何用于信号处理的第三部分实现,如过滤/ fft,可能会将原始指针用于1D或2D数据,因此您必须从QVector中获取这些,我甚至不确定是否可行。如果不是,则必须将每个样本从QVector中取出并将其复制到内存块,然后进行处理,然后将其放回QVector中。
  • 给我们带来了关于QList / QMap的问题:它可以用它们中的任何一个来完成,但它们实际上被设计为具有随机访问迭代器的动态容器,而你有大量固定大小的内存来保存2D数据。可能值得研究一个完全满足您需求的自定义数据容器类。拿一篇论文,写下你真正需要的东西,清除你的想法,忘记Qt / STL / ......然后考虑你需要实现这些的组件,然后再考虑如何实现这些组件(最终在Qt方面)。
  • 对于像这样的代码,最好不要重新分配。预先设置最大历史记录的限制和允许的样本数量(或使其成为配置设置),并在程序开始时分配所需的数组,重新使用相同的内存。
  • 考虑循环缓冲区。当数据以不同的速率进入时(数据获取大多数情况下)很方便,它不需要重新分配,它会自动保存历史记录,如果读取/可以使用最少量的内存副本实现write方法直接返回指向底层内存的指针。
  • 可能会重新考虑您的主题思路,它可能会使您的代码变得不必要地复杂化:最终,来自不同渠道的所有数据必须同时进入屏幕。如果用户在时间x看到来自通道1的数据,则来自通道2的数据也必须来自时间x,否则作为范围没有多大意义。但是假设您在不同线程中处理来自这些通道的数据,则需要在执行实际显示的线程中进行额外同步,因为并非所有数据线程都会在时间x同时完成块的处理。除此之外,考虑到可能没有任何性能增益:如果cpu必须计算30个通道的FFT和100%的剪辑,如果它们被拆分超过30个线程,它真的会更快地计算这些FFT吗?
  • 顺便说一下,这是一个基本问题,我认为实际上并非如此。我已经为不同的设备上的数据采集/处理/可视化/保存做了很多应用程序,我认为这些应用程序是他最难开发的.​​.....

答案 1 :(得分:3)

QObjects乍一看似乎是处理此类数据存储问题的绝佳方法。当我第一次开始使用Qt时,我也想到了同样的事情。但是,这不是它们的用途。关于QObjects在http://www.informit.com/articles/article.aspx?p=667415真正做什么和做什么都有很好的写作。

如果您要做的就是将数据存储在类中,当我阅读您的问题时,请不要使用基于QObject的类。开销会严重影响您的表现。

至于Qt的具体功能对你有什么帮助,Qt没有什么特别的帮助。我发现Qt的容器比标准模板库或者一些专业的容器更容易使用,因为当时我还不太了解它。

从性能的角度来看,我最好的建议是通过编写内存池系统来最小化新/删除数量,或者对每个新读数使用Boost Pool。并且最小化移动数据。