TheRollTideGuy
TheRollTideGuy

Reputation: 13

Embedding Animated Matplotlib in Tkinter Causes Program to Never End

I have searched and have been unable to figure out how to make this program end when the window closes. It works fine for a static pyplot but when I run an animated plot, when I close the window I have to break out of the program with fn-ctrl-b.

#---------Imports
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import time
import tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
#---------End of imports

# Create figure for plotting
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
xs = []
ys = []
zs = []

def animate(i, xs, ys, zs):
    xs.append(time.clock())
    ys.append(time.clock()+np.random.random())

    xs = xs[-100:]
    ys = ys[-100:]

    ax.clear()
    ax.plot(xs, ys)

root = tk.Tk()

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().grid(column=0,row=0)

ani = animation.FuncAnimation(fig, animate, fargs=(xs, ys, zs), interval=5)

tk.mainloop()

I appreciate any help in advance!

Upvotes: 1

Views: 1170

Answers (1)

Mike - SMT
Mike - SMT

Reputation: 15226

My answer will be in OOP. I prefer using a class approach.

As ImportanceOfBeingErnest points out pyplot is likely the culprit so we should use figure from matplotlib here.

After using the figure import from matplotlib instead of the pyplot one I have found that any issue I noticed is now gone. This should fix your problem.

import tkinter as tk
import numpy as np
import time
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import animation, figure


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        fig = figure.Figure()
        canvas = FigureCanvasTkAgg(fig, master=self)
        canvas.get_tk_widget().grid(column=0, row=0)
        self.ax = fig.add_subplot(1, 1, 1)
        self.xs = []
        self.ys = []
        self.zs = []

        self.ani = animation.FuncAnimation(fig, self.animate, interval=5)

    def animate(self, event):
        self.xs.append(time.clock())
        self.ys.append(time.clock() + np.random.random())
        self.xs = self.xs[-100:]
        self.ys = self.ys[-100:]
        self.ax.clear()
        self.ax.plot(self.xs, self.ys)


if __name__ == "__main__":
    App().mainloop()

Upvotes: 2

Related Questions