You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何实现Python动画执行后自动关闭并解决TclError报错

解决Matplotlib动画自动关闭后出现TclError的问题

首先,你的问题根源在于在动画的update函数中提前调用plt.close()——当动画还在执行后续帧的绘制回调时,窗口已经被关闭,Tkinter后端找不到对应的应用实例,就会抛出TclError: this isn't a Tk application

正确的解决方案:利用动画的结束回调关闭窗口

我们可以借助FuncAnimationfinished事件,在动画完全结束后再关闭窗口,而不是在update里强制关闭。修改后的代码如下:

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from matplotlib.animation import FuncAnimation
plt.style.use('classic')

def update(step, arr, axis, max_step):
    print(step, max_step)
    for i in range(5):
        for j in range(5):
            axis[i, j].xaxis.set_major_locator(plt.NullLocator())
            axis[i, j].yaxis.set_major_locator(plt.NullLocator())
            if arr[step][i, j] == 10:
                axis[i, j].imshow(Image.open('A.jpg'), cmap="bone")
            else:
                axis[i, j].imshow(Image.open('B.jpg'), cmap="bone")
    # 移除update内的强制关闭逻辑
    return axis

def close_figure(event):
    # 动画完全结束后再关闭窗口
    plt.close(event.canvas.figure)

if __name__ == '__main__':
    # 第一个动画流程
    a = []
    for i in xrange(5):
        temp = np.zeros((5, 5))
        temp[i, i] = 10
        a.append(temp)
    fig, ax = plt.subplots(5, 5, figsize=(5, 5))
    fig.subplots_adjust(hspace=0, wspace=0)
    
    anim = FuncAnimation(fig, update, frames=5, fargs=(a, ax,4), interval=200, repeat=False)
    # 绑定动画结束事件到关闭函数
    anim.finished.connect(close_figure)
    plt.show()

    # 第二个动画流程
    a = []
    for i in xrange(5):
        temp = np.zeros((5, 5))
        temp[i, i] = 10
        a.append(temp)
    fig, ax = plt.subplots(5, 5, figsize=(5, 5))
    fig.subplots_adjust(hspace=0, wspace=0)
    
    anim = FuncAnimation(fig, update, frames=5, fargs=(a, ax,4), interval=200, repeat=False)
    anim.finished.connect(close_figure)
    plt.show()

为什么这个方案有效?

  • anim.finished.connect(close_figure)会在动画的所有帧都执行完毕、动画循环完全结束后,才触发关闭窗口的操作,避免了动画回调还在运行时窗口被提前关闭的冲突。
  • 移除update里的plt.close(),让动画正常完成所有帧的绘制,再由结束回调处理窗口关闭,从根源上避免了TclError。

额外优化建议

如果你想让代码更简洁,可以把重复的动画创建逻辑封装成函数:

def create_animation():
    a = []
    for i in xrange(5):
        temp = np.zeros((5, 5))
        temp[i, i] = 10
        a.append(temp)
    fig, ax = plt.subplots(5, 5, figsize=(5, 5))
    fig.subplots_adjust(hspace=0, wspace=0)
    anim = FuncAnimation(fig, update, frames=5, fargs=(a, ax,4), interval=200, repeat=False)
    anim.finished.connect(close_figure)
    plt.show()

if __name__ == '__main__':
    create_animation()
    create_animation()

这样既减少了代码冗余,也能保证两个动画依次自动执行并关闭,不会出现报错。

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

火山引擎 最新活动