在事件处理程序内使用matplotlib动画



我有一个动画,每次用户按下特定键时,我都想发射动画。我有代表动画图(因此每帧不同的绘图)和一个空图的数据,因此想法是,当您按R(例如)动画绘图运行时,如果您再次按R,它将再次运行。以下代码有效:

### Lots of code before
fig = plt.figure()
anim = animation.FuncAnimation(fig, animate, repeat=True)
plt.show()

其中 animate是我写的函数。当我运行此操作时,Matplotlib窗口会弹出,动画一遍又一遍地运行。这很好,但是我希望动画以命令开火,所以我这样做了:

### Lots of code before
def press(event):
    if event.key == "r":
        print("r") # for debugging purposes
        anim = animation.FuncAnimation(fig, animate)
fig = plt.figure()
fig.canvas.mpl_connect("key_press_event", press)
plt.show()

事件登记为print所证明的,但什么也没有发生,只是一个空的情节窗口。现在,我读到这是不起作用的,因为动画对象在功能结束后需要保持活力,因此我在创建动画对象之前将global anim添加到了事件处理程序中,现在当我按R时,该程序简单地停止,然后绘图窗口关闭。

如果FuncAnimation调用在某些功能中,则global方法可以正常工作,例如:

def f():
    global anim
    anim = animation.FuncAnimation(fig, animate)
f()

,但不在活动处理程序中。

我该怎么办?如何在事件处理程序中创建动画对象并使其保持活力?

更新:显然导致崩溃的原因是FuncAnimation呼叫中的blit=True(我在示例中没有包括在示例中,因为我认为这是无关紧要的)。设置blit=False停止崩溃,但是当我触发事件时,仍然什么也不会发生。

您必须对动画对象进行实时参考,或者(和计时器)收集垃圾。请参阅http://matplotlib.org/devdocs/api/animation_api.html#animation

奇怪的是,global技术在事件回调中不起作用,但是如果是这样,最好的方法可能是使小型助手类

class AnimManager:
    def __init__(self):
        self.anim = None
    def __call__(self, event):
        fig = make_a_figure_function()
        self.anim = animation.FuncAnimation(fig, animate)
am = AnimManager()
fig.canvas.mpl_connect("key_press_event", am) 

这不是一个完整的答案,但希望它对有相同问题的任何人有帮助:受 @tacaswell上面的评论的启发,我尝试将后端切换到tkagg,现在可以使用。也许是QT的错误?

最新更新