我制作了一个简单的 tkinter GUI,顶部有可以在不同框架之间切换的按钮。这些框架包含使用 matplotlib 制作的各种 2D 图形。看起来像这样:
每个图形的二维数据大小为1000x1000,总共25个图形。所以你可以想象这需要很长时间才能加载。
我不介意 GUI 最初加载需要很长时间,因为我不希望 matplotlib 很快,但我不希望切换帧时出现延迟。
这是我的代码的样子。我已经尽力删除了尽可能多的不必要的内容,抱歉有点长。
# insert libraries here
#
#
#
class App(tk.Tk):
def __init__(self):
super().__init__()
self.menu_list = ['Velocity','Momentum flux','Pressure','Force','Compare analytic','Compare custom']
self.read_data()
self.menu()
self.make_frames()
self.protocol("WM_DELETE_WINDOW", self.on_closing)
self.mainloop()
def read_data(self):
# insert code to read data from hdf5 file here
#
#
#
def menu(self):
# Make a frame for the menu
self.menu_frame = tk.Frame(self)
# Make a button for each option and link the command
for i, name in enumerate(self.menu_list):
tk.Button(self.menu_frame, text = name, command = lambda name = name: self.button_pressed(name)).grid(row = 0, column = i)
# Put menu at the top of the screen
self.menu_frame.grid(row = 0, column = 0, sticky = 'nw')
def button_pressed(self, name):
# Switch frame
for n in self.menu_list:
if n == name:
self.frame_dict[n].grid()
else:
self.frame_dict[n].grid_forget()
def make_frames(self):
# Initialise a dictionary to hold all the graph frames
self.frame_dict = {}
# Initialise the frames
for name in self.menu_list:
self.frame_dict[name] = tk.Frame(self)
# Plot figures in the frames
# insert various functions here for each frame, for example:
self.plot_figs_in_frame( [['u','v'],['du','dv']], self.frame_dict[self.menu_list[0]])
#
#
#
# Put each graph frame below the menu frame
for name in self.menu_list:
self.frame_dict[name].grid(row = 1, column = 0)
# Choose a frame to start on
self.button_pressed(self.menu_list[0])
def plot_figs_in_frame(self, varlist, frame):
rows = len(varlist)
columns = len(varlist[0])
for i, row in enumerate(varlist):
for j, var in enumerate(row):
fig = self.make_fig(var)
canvas = FigureCanvasTkAgg(fig, master = frame)
canvas.draw()
canvas.get_tk_widget().grid(row = i, column = j, sticky='nesw')
plt.close(fig)
def make_fig(self, other_inputs):
# insert matplotlib stuff here
#
#
#
return fig
def on_closing(self):
self.destroy()
self.quit()
App()
我想我可以通过制作所有图形并将它们放置在主循环之前的框架中来解决这个问题。这样我只需要在帧之间切换时执行frame.grid()和frame.grid_forget()即可。但是,每当我第一次按下按钮时,都会出现明显的延迟(按下一次按钮后的延迟要少得多)。
有没有办法预加载帧,以减少按下按钮时的延迟?
这是我改变的
def plot_figs_in_frame(self, varlist, frame, size = 400):
rows = len(varlist)
columns = len(varlist[0])
for i, row in enumerate(varlist):
for j, var in enumerate(row):
fig = self.make_fig(var, self.var_dict[var],size)
fig.savefig('./figures/{}.png'.format(var),dpi = 300)
plt.close(fig)
image = Image.open('./figures/{}.png'.format(var))
image.thumbnail((size, size))
photo = ImageTk.PhotoImage(image)
label = ttk.Label(frame, image = photo)
label.image = photo
label.grid(row = i, column = j, sticky='nesw')