Reputation: 4623
I have an animation I would like to fire each time the user presses a specific key. I have data that represents an animated plot (so one different plot per frame) and an empty plot, so the idea is that when you press R
(for example) the animated plot runs, and if you press R
again it runs again. The following code works:
### Lots of code before
fig = plt.figure()
anim = animation.FuncAnimation(fig, animate, repeat=True)
plt.show()
where animate
is a function I wrote. When I run this the Matplotlib window pops up and the animation runs over and over. This is fine, but I'd like the animation to fire on command, so I did this:
### 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()
The event registers as evidenced by the print
, but nothing happens, just an empty plot window. Now, I read that this doesn't work because the animation object needs to stay alive after the function ends, so I added global anim
to the event handler before I create the animation object, and now when I press R
the program simply stops and the plot window closes.
The global
approach works fine if the FuncAnimation
call is inside some function, like this:
def f():
global anim
anim = animation.FuncAnimation(fig, animate)
f()
but not inside the event handler.
What should I do? How do I create an animation object inside the event handler and make it stay alive?
Update: apparently what causes the crash is having blit=True
in the FuncAnimation
call (which I didn't include in my example since I thought it was irrelevant). Setting blit=False
stops the crashing, but still nothing happens when I trigger the event.
Upvotes: 0
Views: 1829
Reputation: 4623
This is not a complete answer but hopefully it may be of help to anyone with the same problem: inspired by @tacaswell's comment above I tried switching backends to TkAgg, and now it works. Maybe it's a bug with QT?
Upvotes: 0
Reputation: 87536
You have to keep a live refernce to the animation object or it (and it's timers) get garbage collected. See http://matplotlib.org/devdocs/api/animation_api.html#animation
It is odd that the global
technique does not work in the event callback, but if that is the case, the best approach is probably to make a small helper class
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)
Upvotes: 1