Tkinter与matplotlib FuncAnimation累积延迟致GUI冻结问题求助
问题:Tkinter+Matplotlib实时绘图随数据量增加出现延迟累积
我基于Python 3开发了一个Tkinter项目,用于绘制不同传感器的实时数据:
- 用Tkinter搭建GUI,通过
matplotlib.animation.FuncAnimation实现每1秒更新一次的实时绘图 - 点数较少时运行正常,但超过300-400点后开始出现延迟累积,最终冻结。初始数据获取间隔约1秒,随时间推移间隔呈线性增长
- 绘制“迭代次数-X轴、迭代间隔-Y轴”的图表可复现问题,延长更新间隔结果一致
- 尝试将动画函数放入独立线程无效;仅用延迟数据更新Tkinter标签无此问题,说明问题与绘图创建/更新相关
- 开启/关闭blit均无帮助,倾向于关闭blit
复现代码
import tkinter as tk import matplotlib.pyplot as plt from matplotlib.backends import backend_tkagg as bk import matplotlib.animation as animation import numpy as np import time import threading class Application(tk.Frame): def __init__(self, master=None, **kwargs): tk.Frame.__init__(self, master, **kwargs) # ============================================================================= # # Test 1 flags initialization # ============================================================================= self.ani = None # ============================================================================= # Canvas frame # ============================================================================= self.fig = plt.figure(figsize=(15,5)) frm = tk.Frame(self) frm.pack() self.canvas = bk.FigureCanvasTkAgg(self.fig, master=frm) self.canvas.get_tk_widget().pack() # ============================================================================= # # Figure initialization # ============================================================================= self.ax = self.fig.add_subplot(1,1,1) self.ax.plot([],[],'-k', label='delta time') self.ax.legend(loc='upper right') self.ax.set_xlabel('n of readings [-]') self.ax.set_ylabel('time difference between readings [s]') # ============================================================================= # # Start/Quick button # ============================================================================= frm4 = tk.Frame(self) frm4.pack(side='top', fill='x') frm_acquisition = tk.Frame(frm4) frm_acquisition.pack() self.button= tk.Button(frm_acquisition, text="Start acquisition", command=lambda: self.on_click(), bg='green') self.button.grid(column = 0, row=0) # ============================================================================= # # Methods # ============================================================================= def on_click(self): '''the button is a start/stop button ''' if self.ani is None: self.button.config(text='Quit acquisition', bg='red') print('acquisition started') return self.start() else: self.ani.event_source.stop() self.button.config(text='Start acquisition', bg='green') print('acquisition stopped') self.ani = None return def start(self): self.starting_time = time.time() self.time = np.array([]) self.ani = animation.FuncAnimation(self.fig, self.animate_thread, interval =1000, blit=False, cache_frame_data=False) #interval in ms self.ani._start() return # Some post suggested to put animate() in an indipendent thread, but did not solve the problem def animate_thread(self, *args): self.w = threading.Thread(target=self.animate) self.w.daemon = True # Daemonize the thread so it exits when the main program finishes self.w.start() return self.w def animate(self, *args): self.time = np.append(self.time, time.time()-self.starting_time) if len(self.time) > 1: self.ax.scatter(len(self.time),self.time[-1]-self.time[-2], c='k') # root.update() # another post suggested root.update() but did not help either return self.ax, if __name__ == "__main__": root = tk.Tk() app=Application(root) app.pack() root.mainloop()
600次迭代后的延迟图

内容的提问来源于stack exchange,提问作者PedroMat8
相关产品推荐
相关产品推荐

