如何预加载 tkinter 框架以防止延迟?

问题描述 投票:0回答:1

我制作了一个简单的 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()即可。但是,每当我第一次按下按钮时,都会出现明显的延迟(按下一次按钮后的延迟要少得多)。

有没有办法预加载帧,以减少按下按钮时的延迟?

python tkinter
1个回答
0
投票
按照@furas的建议,我尝试将图形保存为图像并将图像加载到 tkinter 而不是 matplotlib 图形中。这极大地改善了延迟。

这是我改变的

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')
    
© www.soinside.com 2019 - 2024. All rights reserved.