'How to instantly update the plot by getting values from a Scale widget?
I have a 3d grid system of 3*4*10 grids (nx*ny*nz), and I have assigned a random value to each grid. I want to plot different surfaces of nx*ny (or let's call it a layer).
I have written this code below to do that. In this code, the layer number is obtained from a Scale widget. This code works well and when I change the slider and plot it again, the corresponding surface plots in a top-level window.
Now, I am looking for a way to update the plot instantly using the slider. I want to plot the initial layer using the button and while the top-level window is open, I want to update the plot by moving the slider. I know there are some ways such as trace method or after method to instantly update the results but I cannot figure it out how to use them in this case.
import tkinter as tk
import numpy as np
from matplotlib.figure import Figure
from matplotlib import cm
from matplotlib.colors import ListedColormap
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
class Data:
def __init__(self):
self.layer = tk.IntVar()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
container = tk.Frame(self)
container.pack()
self.data = Data()
self.frames = {}
for F in (page1,):
frame = F(container, self.data)
self.frames[F] = frame
frame.pack()
def show_frame(self, c):
frame = self.frames[c]
frame.tkraise()
class page1(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
frame1 = tk.Frame(self, width=200)
frame1.pack()
label1 = tk.Label(frame1, text="Layer number:")
label1.grid(row=0, column=0, padx=10)
self.h_slider1 = tk.Scale(frame1, from_=1, to=10, orient="horizontal", length=100, resolution=1, variable=self.data.layer)
self.h_slider1.grid(row=0, column=1)
self.button = tk.Button(frame1, text="plot", command=self.plot)
self.button.grid(row=1, column=0, columnspan=2, pady=20)
np.random.seed(2)
self.num = list(np.random.randint(low=1, high=10, size=120))
def plot(self):
self.top = tk.Toplevel()
nx = 3
ny = 4
num_reshaped = np.array(self.num).reshape(10, nx*ny)
layer = num_reshaped[self.data.layer.get()-1:self.data.layer.get(), :]
layer = layer.reshape(nx, ny)
print(layer)
x, y = np.mgrid[slice(0, nx+1, 1), slice(0, ny+1, 1)]
self.figure = Figure(figsize=(4, 4))
ax = self.figure.add_subplot(111)
col_type = cm.get_cmap('rainbow', 256)
newcolors = col_type(np.linspace(0, 1, 1000))
white = np.array([1, 1, 1, 1])
newcolors[:1, :] = white
newcmp = ListedColormap(newcolors)
c = ax.pcolormesh(x, y, layer, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
ax.figure.colorbar(c)
canvas = FigureCanvasTkAgg(self.figure, self.top)
canvas.draw()
canvas.get_tk_widget().pack()
self.top.mainloop()
app = SampleApp()
app.mainloop()
Solution 1:[1]
I found a solution for that.
import tkinter as tk
import numpy as np
from matplotlib.figure import Figure
from matplotlib import cm
from matplotlib.colors import ListedColormap
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
class Data:
def __init__(self):
self.layer = tk.IntVar()
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
container = tk.Frame(self)
container.pack()
self.data = Data()
self.frames = {}
for F in (page1,):
frame = F(container, self.data)
self.frames[F] = frame
frame.pack()
def show_frame(self, c):
frame = self.frames[c]
frame.tkraise()
class page1(tk.Frame):
def __init__(self, parent, data):
super().__init__(parent)
self.data = data
frame1 = tk.Frame(self, width=200)
frame1.pack()
label1 = tk.Label(frame1, text="Layer number:")
label1.grid(row=0, column=0, padx=10)
self.h_slider1 = tk.Scale(frame1, from_=1, to=10, orient="horizontal", length=100, resolution=1, variable=self.data.layer)
self.h_slider1.grid(row=0, column=1)
self.button = tk.Button(frame1, text="plot", command=self.plot)
self.button.grid(row=1, column=0, columnspan=2, pady=20)
np.random.seed(2)
self.num = list(np.random.randint(low=1, high=10, size=120))
self.button['command'] = self.open
self.h_slider1['command'] = self.update
def plot(self, var, window):
global ax, newcmp, nx, ny, x, y, num_reshaped
nx = 3
ny = 4
num_reshaped = np.array(self.num).reshape(10, nx * ny)
layer = num_reshaped[var - 1:var, :]
layer = layer.reshape(nx, ny)
x, y = np.mgrid[slice(0, nx + 1, 1), slice(0, ny + 1, 1)]
self.figure = Figure(figsize=(4, 4))
ax = self.figure.add_subplot(111)
col_type = cm.get_cmap('rainbow', 256)
newcolors = col_type(np.linspace(0, 1, 1000))
white = np.array([1, 1, 1, 1])
newcolors[:1, :] = white
newcmp = ListedColormap(newcolors)
c = ax.pcolormesh(x, y, layer, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
ax.figure.colorbar(c)
self.canvas = FigureCanvasTkAgg(self.figure, window)
self.canvas.draw()
self.canvas.get_tk_widget().pack()
def open(self):
self.toplevel = tk.Toplevel()
self.toplevel.geometry('+500+100')
self.plot(self.data.layer.get(), self.toplevel)
def update(self, *args):
var = self.data.layer.get()
layer = num_reshaped[var - 1:var, :]
layer = layer.reshape(nx, ny)
ax.pcolormesh(x, y, layer, cmap=newcmp, edgecolor='lightgrey', linewidth=0.003)
self.canvas.draw()
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | pymn |
