0

Im using function plot_graph() which is triggered everytime you open Graph window, my question is: How to plot graph with this function everytime on same place?

plot_graph function looks like this:

def plot_graph(self,event):

df_1 = self.controller.df_1
df_2 = self.controller.df_2
df_3 = self.controller.df_3
df_4 = self.controller.df_4

f = Figure(figsize=(5, 5), dpi=100)
a = f.add_subplot(111)
a.plot(df_1['mean'])
a.plot(df_2['mean'])
a.plot(df_3['mean'])
a.plot(df_4['mean'])
a.legend(['bsl morning', '1st expo', 'bsl noon', '2nd expo'])

canvas = FigureCanvasTkAgg(f, self)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)

And im calling this function with self.bind("<<ShowGraph>>", self.plot_graph)

After second call of this function program starts create second graph under first one, on and on. Output of program, as you can see on image.I want to prevent this and have only one graph. Thank you for help!

milkz-boi
  • 45
  • 3
  • Why did you bind it? Why don't you just call the function normally with `self.plot_graph()`? – Novel Jun 18 '19 at 19:24

1 Answers1

0

I believe you have two choices:

  1. destroy the canvas before creating a new one. See Using tkinter -- How to clear FigureCanvasTkAgg object if exists or similar?
  2. (I think this is a better method) create the figure/canvas in the init section, and reuse those objects to plot new data:

The following demonstrates option #2:

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import tkinter
import numpy as np


class MyClass:
    def __init__(self, frame):
        self.frame = frame
        self.fig = Figure(figsize=(5, 5), dpi=100)
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(self.fig, self.frame)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=True)
        self.button = tkinter.Button(self.frame, text="plot", command=self.plot_graph)
        self.button.pack()

    def plot_graph(self):
        x, y = np.random.random(size=(2, 10))
        self.ax.cla()
        self.ax.plot(x, y)
        self.canvas.draw()


root = tkinter.Tk()
MyFrame = tkinter.Frame(root)
MyClass(MyFrame)
MyFrame.pack()
root.mainloop()
Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75
  • Instead of clearing and replotting, it's better to create and save the line instance with `self.line, = self.ax.plot([], [])` in the initial method, and then update the data in the line with `self.line.set_data(x, y)`. – Novel Jun 18 '19 at 21:25
  • That's true, even better – Diziet Asahi Jun 18 '19 at 21:54