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

如何正确中断嵌入tkinter的matplotlib创建的动画?

解决Matplotlib动画嵌入Tkinter后无法正确中断的问题

问题根源

你用del fig, ani删除实例的方式无法彻底终止后台运行的动画。FuncAnimation依赖内部的定时器(event source)持续触发帧更新,即使实例引用被删除,这些定时器仍会在后台运行,多次点击按钮后,积累的动画进程会导致界面卡顿。

修复方案

要彻底中断旧动画,需要:

  1. 先停止旧动画的事件源,终止其定时更新
  2. 销毁旧的Tkinter画布控件,避免重复创建的控件占用资源
  3. 再清理旧实例并创建新动画

修改后的完整代码

import matplotlib
import matplotlib.backends.backend_tkagg as tkagg
import matplotlib.animation as animation 
import numpy as np
import tkinter as tk

fig = None
ani = None
old_figure_widget = None  # 保存旧画布控件引用

def solve():
    global fig, ani, old_figure_widget
    
    # 1. 停止并清理旧动画
    if ani is not None:
        ani.event_source.stop()  # 终止动画的定时更新
        ani = None  # 释放动画实例引用
    
    # 2. 销毁旧画布控件
    if old_figure_widget is not None:
        old_figure_widget.destroy()
    
    # 3. 清理旧figure
    if fig is not None:
        del fig
    
    # 创建新figure和画布
    fig = matplotlib.figure.Figure() 
    aCanvas = tkagg.FigureCanvasTkAgg(fig, master=win)
    old_figure_widget = aCanvas.get_tk_widget()
    old_figure_widget.grid(row=0, column=3, rowspan=10)
    
    # 动画数据与绘图设置
    ti, tf, dt, delay = 0, 10, 0.01, 15
    t = np.arange(ti, tf, dt)
    x1 = np.sin(t)
    N = len(t)
    
    ax2 = fig.add_subplot(xlim=(0, t[-1]), ylim=(min(x1), max(x1)))
    time_template = 'time = %.1fs'
    time_text = ax2.text(0.05, 0.95, '', transform=ax2.transAxes, 
                         bbox=dict(facecolor='white', edgecolor='black', boxstyle='round,pad=1'))
    massmotion, = ax2.plot([], [], '-')
    CumulativeX1, CumulativeT = [], []
    
    def animate(i):
        CumulativeX1.append(x1[i])
        CumulativeT.append(i*dt)       
        time_text.set_text(time_template % (i*dt))
        massmotion.set_data(CumulativeT, CumulativeX1)
        return time_text, massmotion
    
    ani = animation.FuncAnimation(fig, animate, np.arange(1, N), interval=delay, blit=True)
    fig.canvas.draw()

# 创建GUI
win = tk.Tk()
aButton = tk.Button(win, text='Start Animation', command=solve)
aButton.grid(column=0, row=10, columnspan=2)

win.mainloop()

关键改动说明

  • 添加old_figure_widget变量保存旧画布控件,每次点击时销毁它,避免控件堆积
  • 在删除实例前调用ani.event_source.stop(),彻底终止旧动画的定时任务
  • 调整实例初始化的默认值为None,更方便判断是否存在旧实例

内容的提问来源于stack exchange,提问作者Francesco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 02:01:17