Search code examples
pythonpython-3.xtkinterrefresh

How to reload the frame in tkinter everytime switching the frame?


I am using something similar to bellow code to navigation between windows in my tkinter desktop app. However the problem in bellow approach is that since all the frames are loaded at once, even though when i switch windows, it still returns the previous page. however in my use case i am loading metadata from database(picklist values) so i want to reload each frame whenever i switch the windows? How do i modify this code in such a way that every time i switch to a different frame, it reload the frame again.

import tkinter as tk


LARGE_FONT= ("Verdana", 12)


class SeaofBTCapp(tk.Tk):

    def __init__(self, *args, **kwargs):
        
        tk.Tk.__init__(self, *args, **kwargs)
        container = tk.Frame(self)

        container.pack(side="top", fill="both", expand = True)

        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames = {}

        for F in (StartPage, PageOne, PageTwo):

            frame = F(container, self)

            self.frames[F] = frame

            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(StartPage)

    def show_frame(self, cont):

        frame = self.frames[cont]
        frame.tkraise()

        
class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self,parent)
        label = tk.Label(self, text="Start Page", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button = tk.Button(self, text="Visit Page 1",
                            command=lambda: controller.show_frame(PageOne))
        button.pack()

        button2 = tk.Button(self, text="Visit Page 2",
                            command=lambda: controller.show_frame(PageTwo))
        button2.pack()


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page One!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = tk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage))
        button1.pack()

        button2 = tk.Button(self, text="Page Two",
                            command=lambda: controller.show_frame(PageTwo))
        button2.pack()


class PageTwo(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Page Two!!!", font=LARGE_FONT)
        label.pack(pady=10,padx=10)

        button1 = tk.Button(self, text="Back to Home",
                            command=lambda: controller.show_frame(StartPage))
        button1.pack()

        button2 = tk.Button(self, text="Page One",
                            command=lambda: controller.show_frame(PageOne))
        button2.pack()
        


app = SeaofBTCapp()
app.mainloop()

Solution

  • If you want to recreate each page when it is shown, you have complete control in the show_frame method to do exactly that.

    class SeaofBTCapp(tk.Tk):
    
        def __init__(self, *args, **kwargs):
    
            tk.Tk.__init__(self, *args, **kwargs)
            self.container = tk.Frame(self)
            self.container.pack(fill="both", expand=True)
            self.current_frame = None
            self.show_frame(StartPage)
    
        def show_frame(self, new_frame_class):
            if self.current_frame:
                self.current_frame.destroy()
    
            self.current_frame = new_frame_class(self.container, controller=self)
            self.current_frame.pack(fill="both", expand=True)