0

I am using the following code from Tutorials Point. Here the Quit button stops the program, but I want to pause the animation on another button press. I found other resources that work on onclick() in the figure, but I want to do this from a Pause button.

How can I implement that?

import tkinter
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib import pyplot as plt, animation
import numpy as np

plt.rcParams["figure.figsize"] = [7.00, 3.50]
plt.rcParams["figure.autolayout"] = True

root = tkinter.Tk()
root.wm_title("Embedding in Tk")

plt.axes(xlim=(0, 2), ylim=(-2, 2))
fig = plt.Figure(dpi=100)
ax = fig.add_subplot(xlim=(0, 2), ylim=(-1, 1))
line, = ax.plot([], [], lw=2)

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()

toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
toolbar.update()

canvas.mpl_connect(
    "key_press_event", lambda event: print(f"you pressed {event.key}"))
canvas.mpl_connect("key_press_event", key_press_handler)

button = tkinter.Button(master=root, text="Quit", command=root.quit)
button.pack(side=tkinter.BOTTOM)

toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)

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

def animate(i):
    x = np.linspace(0, 2, 1000)
    y = np.sin(2 * np.pi * (x - 0.01 * i))
    line.set_data(x, y)
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init,frames=200, interval=20, blit=True)

tkinter.mainloop()
solo
  • 71
  • 7

1 Answers1

1

I based my answer on the answer here, which has a great explanation of using a click to pause the animation (which you had already researched). The functionality of my answer is the same as the example, just modifying the pause function to be driven by a tkinter button instead of a mouse click and implementing it in your code.

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
import tkinter as tkinter
from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler

plt.rcParams["figure.figsize"] = [7.00, 3.50]
plt.rcParams["figure.autolayout"] = True

root = tkinter.Tk()
root.wm_title("Embedding in Tk")

plt.axes(xlim=(0, 2), ylim=(-1, 1))
fig = plt.Figure(dpi=100)
ax = fig.add_subplot(xlim=(0, 2), ylim=(-1, 1))
line, = ax.plot([], [], lw=2)

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()

toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
toolbar.update()

canvas.mpl_connect(
    "key_press_event", lambda event: print(f"you pressed {event.key}"))
canvas.mpl_connect("key_press_event", key_press_handler)

button = tkinter.Button(master=root, text="Quit", command=root.quit)
button.pack(side=tkinter.BOTTOM)

# Pause button and function
pause = False
def pause_animation():
    global pause
    pause ^= True
button2 = tkinter.Button(master=root, text="Pause", command=pause_animation)
button2.pack(side=tkinter.BOTTOM)

toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)

def animation_data():
    tMax = 100  # 0.01*tMax/dt needs to be an int for smooth animation
    dt = 1      # Changing dt changes the "speed" that the curve moves on the plot
    y = 0.0
    t = 0
    x = np.linspace(0, 2, 1000)
    while t<tMax:   # This is included to reset t so it doesn't get too large for long runs
        if not pause:
            y = np.sin(2 * np.pi * (x - 0.01 *t))
            t = t + dt
        yield x, y

def animate(animation_data):
    x, y = animation_data[0], animation_data[1]
    line.set_data(x, y)
    return line,

ani = animation.FuncAnimation(fig, animate, animation_data, blit=True, interval=10,
    repeat=True)

tkinter.mainloop()
jezza_99
  • 1,074
  • 1
  • 5
  • 17
  • yes I have seen that answer already. But the problem with that code is that it's generating the points in background while the graph is paused and when resumed it's showing the plot from a whole new position instead of the position it was paused. – solo Nov 21 '21 at 07:38
  • @solo I'm sorry but I don't think you've run this. When you press pause it stops recalculating the points and just keeps feeding the same fixed points to the plot, which in effect freezes the image. It only starts recalculating the point when `pause=False`, and this means it starts from where the plot was paused – jezza_99 Nov 21 '21 at 18:15
  • try running it with `print(y[0]` in the line after `x, y = animation_data[0], animation_data[1]`. You will see that when you press pause the value doesn't change, even though it is constantly printing out a "new" value – jezza_99 Nov 21 '21 at 18:16