使用按钮控制Matplotlib实时图表显示与关闭的异常问题
解决Matplotlib实时图表关闭后无法重新打开的问题
问题根源
- 全局定义的
fig和ax在调用plt.close()后会被销毁,再次点击“Graph it”时复用已失效的绘图对象,导致动画无法渲染。 graph()函数中的ani是局部变量,函数执行完毕后会被Python垃圾回收,触发警告且动画无法正常运行。- 全局数据列表
xs、ys、ys2在多次打开图表时会累积旧数据,导致图表显示异常。
修正方案
- 每次点击“Graph it”时,重新创建
fig、ax和数据列表,避免复用已销毁的对象。 - 将动画对象
ani保存为全局变量,防止被垃圾回收。 - 关闭窗口时清空全局动画对象,确保下次创建新动画无冲突。
修正后的完整代码
import datetime as dt import random import matplotlib.pyplot as plt import matplotlib.animation as animation from tkinter import * # 全局变量存储动画对象,防止被垃圾回收 ani = None # 实时绘图更新函数 def animate(i, xs, ys, ys2, ax): num_random = random.randint(0,100) num_random2 = random.randint(0,100) # 添加新数据 xs.append(dt.datetime.now().strftime('%H:%M:%S.%f')) ys.append(num_random) ys2.append(num_random2) # 限制数据长度 xs = xs[-15:] ys = ys[-15:] ys2 = ys2[-15:] # 更新绘图 ax.clear() ax.plot(xs, ys, label='Random 1') ax.plot(xs, ys2, label='Random 2') # 格式化图表 plt.xticks(rotation=45, ha='right') plt.subplots_adjust(bottom=0.30) plt.title('TMP102 Temperature over Time') plt.ylabel('Temperature (deg C)') ax.legend() # 打开图表函数 def graph(): global ani # 每次打开都创建新的绘图对象和数据列表 fig = plt.figure() ax = fig.add_subplot(1, 1, 1) xs = [] ys = [] ys2 = [] # 创建动画并保存为全局变量 ani = animation.FuncAnimation(fig, animate, fargs=(xs, ys, ys2, ax), interval=1000) plt.show() # 关闭图表函数 def clear(): global ani plt.close() # 清空动画对象 ani = None # 初始化Tkinter窗口 root = Tk() root.title('matplot with tkinter test') root.geometry("400x200") my_button = Button(root, text="Graph it", command=graph) my_button.pack() clear_button = Button(root, text="Clear", command=clear) clear_button.pack() root.mainloop()
关键修改点说明
- 新增全局变量
ani存储动画对象,避免被垃圾回收。 graph()函数内每次都创建新的fig、ax和数据列表,确保每次打开都是全新的绘图上下文。animate函数新增ax参数,使用当前创建的坐标轴对象,不再依赖全局失效的ax。- 添加图例区分两条曲线,优化图表可读性。
内容的提问来源于stack exchange,提问作者qmzaim
相关产品推荐
相关产品推荐

