Tkinter中Matplotlib绘图无法移除的问题求助
问题分析
你的核心问题是每次更新图表时都会创建全新的Figure、FigureCanvasTkAgg和Tkinter Widget实例,旧的实例没有被销毁,只是被新Widget视觉覆盖,但实际仍存在于窗口层级中。切换tab时,你销毁的只是最后一次创建的Widget,之前的旧实例因为失去引用无法被清理,导致图表残留。
解决方案
有两种高效修复方式:
方式1:复用已有图表实例(推荐)
初始化时仅创建一次图表相关实例,后续仅更新数据并重绘,从根源避免多实例堆积问题。
修改代码如下:
# 页面初始化时创建一次图表实例(放在b5_updater外部) def init_b5_plot(): fig = Figure(figsize=(250/100, 180/100), dpi=100) pl1 = fig.add_subplot(111) pltwidget = FigureCanvasTkAgg(fig, master=window) tkplt = pltwidget.get_tk_widget() box_pos = page[5]["box_pos"] tkplt.place(x=box_pos[2][0] + 25, y=box_pos[2][1] + 30) return fig, pl1, pltwidget, tkplt # 仅负责更新图表数据的函数 def update_box_1(pl1, pltwidget): pl1.clear() pl1.plot(y) pltwidget.draw() # 修改后的b5_updater def b5_updater(): global tab, asdf, current_after p1 = page[5]["p1"] p2 = page[5]["p2"] # 首次进入页面时初始化图表 if "plt_fig" not in page[5]: page[5]["plt_fig"], page[5]["pl1"], page[5]["pltwidget"], page[5]["plt_wid"] = init_b5_plot() if tab == 5: if asdf == 100: asdf = 0 p1['value'] = asdf p2['value'] = 100 - asdf y.append(asdf) if len(y) >= plot_lim: y.pop(0) asdf += 1 # 仅更新数据,不创建新实例 update_box_1(page[5]["pl1"], page[5]["pltwidget"]) current_after = window.after(20, b5_updater) else: window.after_cancel(current_after) if current_after is not None else None p1.destroy() p2.destroy() page[5]["plt_wid"].destroy() # 清除实例引用 del page[5]["plt_fig"], page[5]["pl1"], page[5]["pltwidget"], page[5]["plt_wid"] print("Closed B5 Successfully")
方式2:创建新实例前销毁旧实例
如果必须每次创建新图表,需在创建前检查并销毁旧Widget实例:
修改b5_updater中tab == 5的分支:
if tab == 5: # ... 其他逻辑保持不变 ... asdf += 1 # 先销毁旧图表(如果存在) if "plt_wid" in page[5] and page[5]["plt_wid"] is not None: page[5]["plt_wid"].destroy() # 再创建新图表 page[5]["plt_wid"], page[5]["pl1"] = plot_box_1(250, 180, box_pos[2][0] + 25, box_pos[2][1] + 30) current_after = window.after(20, b5_updater)
关键注意点
- 避免反复创建
Figure和FigureCanvasTkAgg实例,否则会引发内存泄漏和Tkinter层级残留问题。 - 确保所有Tkinter Widget实例都有明确引用,防止因引用丢失导致无法销毁。
内容的提问来源于stack exchange,提问作者superfast852
相关产品推荐
相关产品推荐

