gpt4 book ai didi

python - matplotlib 和 pyqt4 : update plot in one thread, 画在另一个

转载 作者:太空宇宙 更新时间:2023-11-04 06:26:58 26 4
gpt4 key购买 nike

我正在使用 PyQt4 和 matplotlib 创建一个实时数据监视器 GUI 来创建绘图。 GUI 一次显示多个绘图(大约 6 或 7 个)。为了给 GUI 线程更多的时间和稍微更好的响应时间,我只执行绘图 canvas.draw() 和我在更新绘图数据的线程中执行的所有其他绘图命令。因此,在非 GUI 线程中,我执行诸如 line.set_ydataax.set_ylim 和其他可能需要更新的命令。

两个线程可以通过在初始化时传递给两个线程的字典访问图形和 Canvas 对象。当非 GUI 线程获取数据并更新绘图时,它会通知 GUI 线程使用 Qts 信号(自动连接)重绘 Canvas 。我的线程经验告诉我,我应该使用锁或确保非 GUI 线程以某种方式在重绘时被阻塞,但在我的编码匆忙中,我从来没有把它放进去,直到现在才忘记它。这种情况的关键是我想看到情节的每次更新,而不是在其他线程更新的中间重绘,甚至错过更新(如果这有意义的话)。目前,我认为我只是幸运地把握了时机,事情似乎进展顺利。

另一件可能有帮助的事情是,我通过使用 moveToThread 将 QObject 移动到 QThread 来创建线程。

我的问题是:

  • 我只是走运还是 Qt 只是在做一些神奇的事情?
  • 在 matplotlib canvas/figure 上完成分块的最佳方法是什么?

我可能应该注意到,这是我第一次尝试使 GUI 响应更快(将 matplotlib 命令移到数据线程中),我可能会转向 blit 动画风格的绘图,只更新绘图中发生变化的部分。但我仍然很好奇我到底有多幸运。

感谢您的帮助。

更新/澄清/评论的延续:我希望整个监控系统能够由可能只熟悉 matlab 和 matplotlib 的科学家轻松更改/更新。我并不完全反对改用 pyqwt 来提高速度。就每秒帧数而言,我根本不需要太多,因为标称的每 0.5 秒(最快 0.2 秒)才绘制一次数据。 GUI 响应能力似乎“吃掉了**”,因为有太多的情节。我已经用 matplotlib blitting 对我的代码进行了概念验证,它似乎有很大帮助,如果需要,pyqwt 将会发生。我之前的问题仍然有效。

最佳答案

我偶然发现了类似的问题。我有很多图要画 (~250),所以我的 GUI 窗口最终会显示为卡在 Windows 中。我修改了图形类以作为单独的线程执行绘图。结果 - 我的 GUI 不再挂起,绘图窗口在绘图完成后显示。要使用它,您需要创建 PlotDialog 实例并使用 plot_data 参数调用 draw_plots 方法。 plot_data 是一个字典列表,每个字典代表子图。每个子图都有以下键(和相应的数据):titlexlabelylabeldata。希望这是有道理的。

这是我的代码:

import math

from PyQt4 import QtCore, QtGui

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar


class MyFigure(Figure, QtCore.QThread):
def __init__(self, parent, *args, **kwargs):
QtCore.QThread.__init__(self, parent)
Figure.__init__(self, *args, **kwargs)

self.plot_data = list()

def start_plotting_thread(self, plot_data, on_finish=None):
""" Start plotting """
self.plot_data = plot_data

if on_finish is not None:
self.finished.connect(on_finish)

self.start()

def run(self):
""" Run as a thread """
# Figure out rows and columns
total_plots = len(self.plot_data)

columns = int(math.sqrt(total_plots))
if columns < 1:
columns = 1

rows = int(total_plots / columns)
if (total_plots % columns) > 0:
rows += 1
if rows < 1:
rows = 1

# Plot Data
for plot_index, _plot_data in enumerate(self.plot_data):
plot_number = plot_index + 1
args = (rows, columns, plot_number)
kwargs = {
'title': _plot_data['title'],
'xlabel': _plot_data['xlabel'],
'ylabel': _plot_data['ylabel']
}

figure = self.add_subplot(*args, **kwargs)

figure.plot(_plot_data['data'])


class PlotDialog(QtGui.QDialog):
def __init__(self, parent):
super(PlotDialog, self).__init__(parent, QtCore.Qt.WindowMinMaxButtonsHint | QtCore.Qt.WindowCloseButtonHint)

self.figure = MyFigure(self)
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas, self)

self.layout = QtGui.QGridLayout()
self.setLayout(self.layout)

layout = [
[self.canvas],
[self.toolbar],
]

for row_index, columns in enumerate(layout):
if type(columns) is list:
for column_index, widget in enumerate(columns):
if widget is not None:
self.layout.addWidget(widget, row_index, column_index)

def draw_plots(self, plot_data):
""" Plot Plots """
self.figure.start_plotting_thread(plot_data, on_finish=self.finish_drawing_plots)

def finish_drawing_plots(self):
""" Finish drawing plots """
self.canvas.draw()
self.show()

关于python - matplotlib 和 pyqt4 : update plot in one thread, 画在另一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7294145/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com