I have written a very simple code to have a scatter plot in matplotlib subplot. I can plot based on the values for x, y1
with the plot()
function. I want to know if I got new values such as y2
through another function, how to update it in on the figure? I checked other posts in this regard and there were some suggestions to use clear()
, destroy()
, delete()
in the update() function but none of them works. I want to keep the settings for the canvas and figure and only replace the new values with the old values.
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
class Data:
def __init__(self):
self.x = tk.IntVar()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.minsize(700, 700)
container = tk.Frame(self)
container.pack()
self.data = Data()
self.frames = {}
for F in (PageOne, ):
frame = F(container, self.data)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
def show_frame(self, c):
frame = self.frames[c]
frame.tkraise()
class PageOne(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
self.button1 = tk.Button(self, text="Plot", command=self.plot)
self.button1.pack()
self.button2 = tk.Button(self, text="update", command=self.update)
self.button2.pack()
self.frame = tk.LabelFrame(self)
self.frame.pack()
def plot(self):
global x
x = [1,2,3,4,5,6,7,8,9]
y1 = [1,2,3,4,5,6,7,8,9]
self.figure = Figure(figsize=(4, 4))
ax = self.figure.add_subplot(111)
ax.scatter(x, y1)
ax.set_title('Test')
ax.set_xlabel('x')
ax.set_ylabel('y')
canvas = FigureCanvasTkAgg(self.figure, self.frame)
canvas.draw()
canvas.get_tk_widget().pack()
toolbar = NavigationToolbar2Tk(canvas, self.frame)
toolbar.pack()
canvas.get_tk_widget().pack()
def update(self):
global x
self.figure.clear()
y2 = [1, 2, 3, 4, 5, 4, 3, 2, 1]
app = SampleApp()
app.mainloop()
CodePudding user response:
I got it to work by a combination of what I suggested and something I found in another post.
Here's how I did it, modifying only your update
function.
def update(self):
global x
self.figure.clear()
ax = self.figure.add_subplot(111)
ax.set_title('Test')
ax.set_xlabel('x')
ax.set_ylabel('y')
x = [1,2,3,4,5,6,7,8,9]
y2 = [1, 2, 3, 4, 5, 4, 3, 2, 1]
ax.scatter(x, y2)
self.figure.canvas.draw()
Here's how I did it using the set_data
method.
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
class Data:
def __init__(self):
self.x = tk.IntVar()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.minsize(700, 700)
container = tk.Frame(self)
container.pack()
self.data = Data()
self.frames = {}
for F in (PageOne, ):
frame = F(container, self.data)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
def show_frame(self, c):
frame = self.frames[c]
frame.tkraise()
class PageOne(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
self.button1 = tk.Button(self, text="Plot", command=self.plot)
self.button1.pack()
self.button2 = tk.Button(self, text="update", command=self.update)
self.button2.pack()
self.frame = tk.LabelFrame(self)
self.frame.pack()
def plot(self):
global x
x = [1,2,3,4,5,6,7,8,9]
y1 = [1,2,3,4,5,6,7,8,9]
self.figure = Figure(figsize=(4, 4))
ax = self.figure.add_subplot(111)
l = ax.plot(x, y1, lw=0, marker='o') # Changed here
self.line1 = l[0] # Changed here
ax.set_title('Test')
ax.set_xlabel('x')
ax.set_ylabel('y')
canvas = FigureCanvasTkAgg(self.figure, self.frame)
canvas.draw()
canvas.get_tk_widget().pack()
toolbar = NavigationToolbar2Tk(canvas, self.frame)
toolbar.pack()
canvas.get_tk_widget().pack()
def update(self):
global x
y2 = [1, 2, 3, 4, 5, 4, 3, 2, 1]
self.line1.set_data(x, y2) # Changed here
self.figure.canvas.draw() # Changed here <-- without this, won't redraw
app = SampleApp()
app.mainloop()
There's a few weird things in your code like global x
that's unused, but that's stuff for another time.