对于实时数据,Tkinter matplotlib 画布更新太慢
Posted
技术标签:
【中文标题】对于实时数据,Tkinter matplotlib 画布更新太慢【英文标题】:Tkinter matplotlib canvas updates too slowly for real time data 【发布时间】:2020-10-31 11:23:30 【问题描述】:我正在使用每秒发送 100 个读数的设备,我希望我的 GUI 有一个显示最后 300 个收集点的数据图。但是,我发现:
将新数据点添加到 y 轴队列
清除已经存在的情节
绘制新的数据列表
重绘画布
每个点之后需要将近 0.2 - 0.4 秒,这非常慢。
这是我目前使用的代码。一个while循环不断检查一个队列,一旦一个新元素被推送到它,它就会以元素作为参数调用update
。任何人都可以提出一些改进效率或替代 matplotlib 的建议吗?
class GraphFrame:
def __init__(self,root,channel,index):
self.root=root
self.frame=tk.Frame(self.root)
self.frame.pack(side=tk.LEFT)
self.y = Queue(maxsize = 300)
self.fig, self.axes = plt.subplots(1,1)
self.axes.plot(list(self.y.queue))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, padx=5, pady=5)
def update(self, new_point):
if self.y.full():
self.y.get()
self.y.put(new_point)
self.fig.axes[0].clear()
self.fig.axes[0].plot(list(self.y.queue))
self.canvas.draw()
编辑:设法解决了这个问题,使用 matplotlib 的 blitting 并将 Tkinter 画布替换为带有图形图像的标签。将尝试在github上上传代码并链接它。
【问题讨论】:
你应该修改线条艺术家,而不是清除图形并从头开始构建。 你能发一份代表数据的清单吗?也许像 15 - 25 个数据点?Queue
是从哪里导入的?
@PaulH 数据点只是来自传感器的浮点读数。当没有人在它前面时,值约为 2000,当有人站在它前面时,值约为 20,000。浮点数没什么特别的。
@PaulH from queue import Queue
【参考方案1】:
我不会为每个新点重建你的图形,而是修改你已经拥有的 LineArtist。
class GraphFrame:
def __init__(self,root,channel,index):
self.root=root
self.frame=tk.Frame(self.root)
self.frame.pack(side=tk.LEFT)
self.y = Queue(maxsize = 300)
self.fig, self.axes = plt.subplots(1,1)
# capture the artist
self.line, = self.axes.plot(list(self.y.queue))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.frame)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, padx=5, pady=5)
def update(self, new_point):
if self.y.full():
self.y.get()
self.y.put(new_point)
# update the artist
self.line.set_xdata(list(range(len(self.y))))
self.line.set_ydata(list(self.y.queue))
【讨论】:
self.line 是一个列表,它给出“列表对象没有属性 set_xdata” 编辑:没关系,我刚刚得到了该列表的第一个元素 [0] @MohamedMoustafa 您是否在作业中包含逗号?如果是这样,您可能只需要从该列表中提取第一个(也是唯一一个?)元素。 ok,self.y 是一个队列,所以我不能使用 len(),所以我使用了 .qsize()。该图不会在视觉上更新,当我调整 GUI 大小时,它会更新,但仅在 x = 0.00 和 y = 0 - 0.04+ 处显示一条垂直线 @MohamedMoustafa 哦,艺术家更新后可能需要self.fig.draw()
self.fig.draw()
给出draw_wrapper() missing 1 required positional argument : 'renderer'
。另外,请记住,这是 tkinter FigureCanvasTkAgg 中的图,而不仅仅是常规的 matplotlib 图。以上是关于对于实时数据,Tkinter matplotlib 画布更新太慢的主要内容,如果未能解决你的问题,请参考以下文章