0

I am working through a tutorial from: https://pythonprogramming.net/embedding-live-matplotlib-graph-tkinter-gui/

I have modified the code quite a bit and broken some things in the process

This question is about calling a function within __init__ I can call a matplotlib animation using this call:

graph = Graph()
ani = graph.start_graphing()

but if I put that call in my Graph class __init__ and then call it, no joy:

class Graph():
    def __init__(self):
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        self.xList = []
        self.yList = []
        ani = self.start_graphing()

    def animate(self, *args):
        self.xList.append(time.time())
        self.yList.append(np.random.random())
        self.ax.clear()
        self.ax.plot(self.xList, self.yList)

    def start_graphing(self):
        print("started")
        return animation.FuncAnimation(self.fig, self.animate, interval=250)

graph = Graph()

Why can I call this function from outside the class, but when I try and call it from the __init__ the program breaks. Note started is printed in both cases

here is the entire program for reference:

#! /usr/bin/python3
# -*- coding: utf-8 -*-

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

matplotlib.use("TkAgg")
LARGE_FONT= ("Verdana", 12)

class Graph():
    def __init__(self):
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        self.xList = []
        self.yList = []
        gsg = self.start_graphing()

    def animate(self, *args):
        self.xList.append(time.time())
        self.yList.append(np.random.random())
        self.ax.clear()
        self.ax.plot(self.xList, self.yList)

    def start_graphing(self):
        print("started")
        return animation.FuncAnimation(self.fig, self.animate, interval=250)

class Window(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        tk.Tk.wm_title(self, "PlotCPU")
        container = tk.Frame(self)
        container.pack(side="top", fill="both", expand = True)
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)
        self.frames = {}
        for F in (StartPage, GraphPage):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")
        self.show_frame(GraphPage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()

class StartPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Start Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = ttk.Button(self, text="Graph Page",
                            command=lambda: controller.show_frame(GraphPage))
        button1.pack()

class GraphPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Graph Page!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = ttk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage))
        button1.pack()

        canvas = FigureCanvasTkAgg(graph.fig, self)
        canvas.draw()
        canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)

graph = Graph()
app = Window()
app.mainloop()
posop
  • 511
  • 2
  • 7
  • 17
  • 3
    It's probably related to the object returned by `FuncAnimation` being garbage-collected after `start_graphing` exits. Return the value instead, and use `ani = graph.start_graphing()`. – chepner Jul 25 '19 at 15:38
  • @chepner exactly correct. now I can do `graph = Graph()` and `ani = graph.start_graphing()`. I would like to move that statement into the `Graph.__init__` but putting `ani = self.start_graphing()` to the end of my __inti__ function is back to no joy. I thought I could call a function from __init__ using that language. Any ideas what the new hiccup is? – posop Jul 25 '19 at 17:23

0 Answers0