【发布时间】:2011-11-09 18:49:07
【问题描述】:
我正在使用 PyQt4 和 matplotlib 创建一个实时数据监视器 GUI 来创建绘图。 GUI 一次显示多个图(大约 6 或 7 个)。为了给 GUI 线程更多的时间和稍微更好的响应时间,我只执行绘图 canvas.draw() 以及我在更新绘图数据的线程中执行的所有其他绘图命令。因此,在非 GUI 线程中,我执行 line.set_ydata、ax.set_ylim 之类的命令以及其他可能需要更新的内容。
两个线程可以通过在初始化时传递给两个线程的字典来访问图形和画布对象。当非 GUI 线程获取数据并更新绘图时,它会向 GUI 线程发出信号以使用 Qts 信号(自动连接)重新绘制画布。我的线程经验告诉我,我应该使用锁或确保以某种方式在重绘时阻塞非 GUI 线程,但在我的编码匆忙中,我从来没有把它放进去,直到现在才忘记它。这种情况的关键是我希望看到情节的每次更新,而不是在其他线程更新的中间重绘,甚至错过更新(如果有意义的话)。目前,我想我只是在时机上很幸运,而且一切似乎都很好。
另一件可能有助于了解的事情是,我通过使用 moveToThread 将 QObject 移动到 QThread 来创建线程。
我的问题是:
- 是我运气好还是 Qt 只是做了一些神奇的事情?
- 在 matplotlib 画布/图形上完成阻塞的最佳方法是什么?
我可能应该注意到,这是我第一次尝试使 GUI 更具响应性(将 matplotlib 命令移动到数据线程中),并且我可能正在转向只更新绘图中发生变化的部分的 blit 动画样式绘图。但我仍然很好奇我有多幸运。
感谢您的帮助。
来自 cmets 的更新/澄清/继续:我希望可能只熟悉 matlab 和可能 matplotlib 的科学家能够轻松更改/更新整个监控系统。我并不完全反对更改为 pyqwt 以提高速度。就每秒帧数而言,我真的不需要太多,因为正在绘制的数据仅在标称每 0.5 秒出现一次(最快为 0.2 秒)。 GUI 响应似乎只是“吃掉了 **”,因为有太多的情节。我已经用 matplotlib blitting 对我的代码进行了概念验证,它似乎有很大帮助,如果需要,pyqwt 会发生。我之前的问题仍然存在。
【问题讨论】:
-
matplotlib 在不使用 blitting 的情况下非常慢。即使有了它,对于数据监控,我建议使用其他东西。看看packages.python.org/guiqwt/index.html
-
我确实看过 qwt,因为很多人说它比 matplotlib 快得多。我不想马上转向它的原因是为了让熟悉 matplotlib(实际上是 matlab)的人(科学家)更容易将绘图添加到整体数据监视器包中。而且我没有过多研究它,但如果它不太难,也许我会制作一个类似于使用 matplotlib 的界面。
-
我非常喜欢 matplotlib,我将它用于我所有的出版物图形。但是对于交互式使用,您必须使用 blitting 来获得合理的速度,这很麻烦,否则速度对于我的需求来说太差了(多个绘图大约 20 fps)。
-
现在实现类似的东西。戴夫,你认为你可以分享一些代码吗?这是我的想法。您必须使用多个类,一个基于 PyQt 的 QDialog 或类似的 GUI 输出。另一个是基于 QThread 的工人阶级。一旦 QThread 完成绘图,它将使用 PyQt 信号引擎将图形和画布实例传递给 GUI 对象。我尝试将 QDialog 和 QThread 组合成一个类,但显然你做不到。 (我相信你可以做到,但使用 2 个单独的类更容易)
-
@Barmaley 这个问题已经有将近 5 年的历史了。我不确定我的代码是否适用于较新版本的 mpl。我建议您对应该如何使用 Qt 线程(由 QThread“拥有”的 QObject)进行更多研究。您可能不想通过信号传递图形和画布。它们是大型复杂对象,画布实际上是一个 GUI 元素,因此它保留在 GUI 线程中。另外,为什么是 QDialog?只需在其中制作一个带有 mpl 画布的普通 QWidget。经过一些研究,如果您仍然需要指导,您应该提出自己的 stackoverflow 问题或询问 mpl 邮件列表。
标签: python qt4 matplotlib pyqt4