简体   繁体   中英

How to use matplotlib button in conjunction with the animation function?

I want to write a code where the animation function in matplotlib starts plotting only after the matplotlib button widget is clicked by me. Here are my steps:

  1. I create a empty plot.
  2. I press my mouse anywhere on the plot which activates click events and the x and y coordinates are stored in a list.
  3. I click on press button which runs the animation function.
  4. The animation function plots by using the stored x and y coordinates.

I got successful in the storing the x and y coordinates but the press button doesn't give me the animated plot that I need. This is the first error I am facing.

The second error is my click event also stores the coordinates of where I press the button. I don't want coordinates during button press. I just the coordinates on the empty plot.

from matplotlib.widgets import Button
from matplotlib.animation import FuncAnimation

x_coord,y_coord = [],[]

fig = plt.figure()
axis = fig.add_subplot(111,xlim=(-5,15),ylim=(-5,15))
line, = axis.plot([],[],lw=3)

def init():
    line.set_data([],[])
    return line, 

def animate(i):
    x_points = [0,x_coord[i]]
    y_points = [0,y_coord[i]]
    line.set_data(x_points,y_points)
    return line, 

def onclick(event):
    print(event.xdata,event.ydata)
    x_coord.append(event.xdata)
    y_coord.append(event.ydata)


def buttonPress(pressevent):
    print('pressed')
    print(x_coord)
    ani = FuncAnimation(fig,animate,init_func=init,frames=len(x_coord),interval=100,blit=False)
    
    

cid = fig.canvas.mpl_connect('button_press_event',onclick)

axprev = plt.axes([0.5,0,0.1,0.1])
button = Button(axprev,'press')
button.on_clicked(buttonPress)

plt.show()```

The second error is easy to fix, you can test whether the click was in or out of the axes region by using event.inaxes

The animation issue is due to the fact that you are creating the animation object in a function, and that it is immediately garbage-collected at the end of the function. The [documentation for FuncAnimation][2] states:

it is critical to keep a reference to the instance object. The animation is advanced by a timer (typically from the host GUI framework) which the Animation object holds the only reference to. If you do not hold a reference to the Animation object, it (and hence the timers), will be garbage collected which will stop the animation.

One way to get around that is to keep the animation object in a global variable. A cleaner way would be to encapsulate your code in a custom class and store the animation as a property of that class.

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.widgets import Button

x_coord, y_coord = [], []

fig = plt.figure()
axis = fig.add_subplot(111, xlim=(-5, 15), ylim=(-5, 15))
line, = axis.plot([], [], lw=3)
ani = None


def init():
    line.set_data([], [])
    return line,


def animate(i):
    x_points = [0, x_coord[i]]
    y_points = [0, y_coord[i]]
    line.set_data(x_points, y_points)
    return line,


def onclick(event):
    if event.inaxes is axis:
        print(event.xdata, event.ydata)
        x_coord.append(event.xdata)
        y_coord.append(event.ydata)


def buttonPress(pressevent):
    global ani
    print('pressed')
    print(x_coord)
    ani = FuncAnimation(fig, animate, init_func=init, frames=len(x_coord), interval=100, blit=False)


cid = fig.canvas.mpl_connect('button_press_event', onclick)

axprev = plt.axes([0.5, 0, 0.1, 0.1])
button = Button(axprev, 'press')
button.on_clicked(buttonPress)

plt.show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM