0

I am trying to get a live matplotlib graph working in Tkinter while using a class structure. I am using the code from this stackoverflow question which successfully runs a matplotlib graph in Tkinter(does not use class structure). Every time I try to run the code I altered I am given a

TypeError: __init__ takes exactly 2 arguments (1 given)

I know this TypeError type question has been asked before. I tried to use this but the answer provided did not solve my problem.

The line of code that seems to be the problem is:

ani = animation.FuncAnimation(Window().fig, Window().animate(), interval=1000, blit=Fals

I have tried altering how I call fig and animate but nothing seems to work.


import Tkinter as Tk
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
xar = []
yar = []

class Window:
    def __init__(self,master):
        frame = Tk.Frame(master)
        fig = plt.figure(figsize=(14, 4.5), dpi=100)

        self.ax = fig.add_subplot(1,1,1)
        self.ax.set_ylim(0, 100)
        self.line, = self.ax.plot(xar, yar)

        self.canvas = FigureCanvasTkAgg(fig,master=master)
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
        frame.pack()
    def animate(self,i):
        yar.append(99-i)
        xar.append(i)
        self.line.set_data(xar, yar)
        self.ax.set_xlim(0, i+1)

root = Tk.Tk()
ani = animation.FuncAnimation(Window().fig, Window().animate(),interval=1000, blit=False)
app = Window(root)
root.mainloop()
Stop harming Monica
  • 12,141
  • 1
  • 36
  • 56
Bennis
  • 37
  • 7
  • Well, you are calling the WIndow() constructor - twice - and it takes one argument. You aren't passing anything. – Paul Cornelius Nov 21 '17 at 23:24
  • I also tried defining fig outside of the Window() class so I would only call the Window constructor once and it did not work. ani = animation.FuncAnimation(fig, Window().animate,interval=1000, blit=False) – Bennis Nov 21 '17 at 23:30
  • 1
    Leave `fig` where it is. Just create the object once and then access its methods. See my answer. – Paul Cornelius Nov 21 '17 at 23:34

2 Answers2

1

I'm not sure what you are trying to do but you probably want something like this:

root = Tk.Tk()
app = Window(root)
ani = animation.FuncAnimation(app.fig, app.animate(),interval=1000, blit=False)
root.mainloop()

This will not completely solve the problem as there is no argument for the animate function either.

Paul Cornelius
  • 9,245
  • 1
  • 15
  • 24
  • I am trying to replicate this [code](https://stackoverflow.com/questions/42192133/embedding-matplotlib-live-plot-data-from-arduino-in-tkinter-canvas ) only Id like to have it in a class type format. – Bennis Nov 21 '17 at 23:42
1

You have many mistakes:

As Paul Comelius said you have to create instance

app = Window(root)
ani = animation.FuncAnimation(app.fig, app.animate, interval=1000, blit=False)

-

You have to use self.fig inside class to get it later as app.fig

-

animation.FuncAnimation expects callback - it means function name without ().
In you code it will be app.animate.

ani = animation.FuncAnimation(app.fig, app.animate, interval=1000, blit=False)

-

Full working code

import Tkinter as Tk
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

class Window:

    def __init__(self,master):
        frame = Tk.Frame(master)

        self.fig = plt.figure(figsize=(14, 4.5), dpi=100)

        self.ax = self.fig.add_subplot(1,1,1)
        self.ax.set_ylim(0, 100)
        self.line, = self.ax.plot(xar, yar)

        self.canvas = FigureCanvasTkAgg(self.fig, master=master)
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
        frame.pack()

    def animate(self,i):
        yar.append(99-i)
        xar.append(i)
        self.line.set_data(xar, yar)
        self.ax.set_xlim(0, i+1)

xar = []
yar = []

root = Tk.Tk()
app = Window(root)
ani = animation.FuncAnimation(app.fig, app.animate, interval=1000, blit=False)
root.mainloop()
furas
  • 134,197
  • 12
  • 106
  • 148
  • Is this also possible without making the GUI lag every second? If you drag the window over the desktop it is lagging. I try something similar. – K-Doe Jan 19 '19 at 17:02