我正在尝试嵌入一个matplotlib图,它每秒都会更新到PyQt GUI主窗口。
在我的程序中,我使用threading.Timer
通过下面显示的timer
函数每秒调用一次更新函数。我有一个问题:我的程序每秒都会变大 - 每4秒钟大约1k。我最初的想法是append函数(在update_figure
中返回一个新数组)不会删除旧数组?这可能是我问题的原因吗?
def update_figure(self):
self.yAxis = np.append(self.yAxis, (getCO22()))
self.xAxis = np.append(self.xAxis, self.i)
# print(self.xAxis)
if len(self.yAxis) > 10:
self.yAxis = np.delete(self.yAxis, 0)
if len(self.xAxis) > 10:
self.xAxis = np.delete(self.xAxis, 0)
self.axes.plot(self.xAxis, self.yAxis, scaley=False)
self.axes.grid(True)
self.i = self.i + 1
self.draw()
这是我的计时器功能 - 这是通过点击我的PyQt GUI中的按钮触发,然后调用自己,如你所见:
def timer(self):
getCH4()
getCO2()
getConnectedDevices()
self.dc.update_figure()
t = threading.Timer(1.0, self.timer)
t.start()
编辑: 我无法发布我的整个代码,因为它需要大量的.dll包含。所以我会尝试解释这个程序的作用。
在我的GUI中,我希望随着时间的推移显示我的CO 2 值。我的get_co22
函数只返回一个浮点值,我100%确定这个工作正常。使用我的计时器,如上所示,我想继续为matplotlib图添加一个值 - Axes
对象可以作为self.axes
使用。我尝试绘制数据的最后10个值。
编辑2: 在一些discussion in chat之后,我尝试在update_figure()
循环中调用while
并使用一个线程来调用它,并能够创建这个最小的例子http://pastebin.com/RXya6Zah。这改变了代码的结构,以便将update_figure()
调用到以下内容:
def task(self):
while True:
ui.dc.update_figure()
time.sleep(1.0)
def timer(self):
t = Timer(1.0, self.task())
t.start()
但现在程序在5次迭代后崩溃。
答案 0 :(得分:2)
问题绝对不在于如何附加到numpy数组或截断它。
这里的问题在于您的线程模型。将计算循环与GUI控制循环集成起来很困难。
从根本上说,您需要使用GUI线程来控制何时调用更新代码(如果需要,生成一个新线程来处理它) - 这样
在这种情况下,由于您的主窗口由PyQt4控制,您想使用QTimer
(请参阅simple example here)
所以 - 将您的timer
代码改为
def task(self):
getCH4()
getCO2()
getConnectedDevices()
self.dc.update_figure()
def timer(self):
self.t = QtCore.QTimer()
self.t.timeout.connect(self.task)
self.t.start(1000)
这应该有效。保持对QTimer
的引用至关重要 - 因此self.t = QtCore.QTimer()
而不是t = QtCore.QTimer()
,否则QTimer
对象将被垃圾收集。
这是long thread in chat的摘要,澄清了问题,并通过几种可能的解决方案。特别是 - OP在这里设法模拟了一个更简单的可运行示例:http://pastebin.com/RXya6Zah
并且完整的可运行示例的固定版本位于:http://pastebin.com/gv7Cmapr
相关的代码和解释如上所述,但链接可能会帮助任何想要复制/解决问题的人。请注意,它们需要安装PyQt4
答案 1 :(得分:0)
如果你每次创建一个新的数字这很常见。
matplotlib不会释放你创建的数字,除非你问它,有些想法:
pylab.close()
请参阅How can I release memory after creating matplotlib figures