You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 10:20:39