简体   繁体   中英

Switching between different frames in tkinter

I'm trying to learn how to work with frames in tkinter, wrote it in a way every page is a different class:

import tkinter as tk


class App(tk.Tk):

    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Multiple Frames Test")
        self.resizable(False, False)
        StartPage().pack()

    def switch_frames(self, to_remove, to_add):
        to_remove.pack_forget()
        to_add.pack()


class StartPage(tk.Frame, App):

    def __init__(self):
        tk.Frame.__init__(self)
        self.title1 = tk.Label(self, text="This is an awesome label")
        self.title1.grid(row=0, column=0, padx=(20, 20), pady=(20, 20))
        self.switch_btn1 = tk.Button(self, text="Switch to SecondaryPage", command=lambda: self.switch_frames(self, SecondaryPage))
        self.switch_btn1.grid(row=1, column=0, padx=(20, 20), pady=(0, 20))


class SecondaryPage(tk.Frame, App):

    def __init__(self):
        tk.Frame.__init__(self)
        self.title2 = tk.Label(self, text="This is also an awesome label")
        self.title2.grid(row=0, column=0, padx=(20, 20), pady=(20, 20))
        self.switch_btn2 = tk.Button(self, text="Switch to StartPage")
        self.switch_btn2.grid(row=1, column=0, padx=(20, 20), pady=(0, 20))


my_app = App()
my_app.mainloop()

After pressing the button to switch to SecondaryPage I get the error:

File "c:\Users...", line 23, in

self.switch_btn1 = tk.Button(self, text="Switch to SecondaryPage", command=lambda: self.switch_frames(self, SecondaryPage))

File "c:\Users...", line 14, in switch_frames

to_add.pack()

TypeError: pack_configure() missing 1 required positional argument: 'self'

You are passing a class to switch_frames , but switch_frames was designed to accept instances. You need to do one of two things: either create instances of both classes and then pass the proper instances to the function, or redefine switch_frames to create the instances on demand.

Here's what the first solution might look like:

class App(tk.Tk):

    def __init__(self):
        ...
        self.start_page = StartPage()
        self.secondary_page = SecondaryPage()

        # initially hide the secondary page and show the start page
        self.switch_frames(self.secondary_page, self.start_page)

The other solution requires changing switch_frames to accept a class, which it then creates before switching to it. It might look something like this:

class App(tk.Tk):
    def __init__(self):
        ...
        self.current_page = None
        self.switch_frames(StartPage)
        ...

    def switch_frames(self, new_frame_cls):
        if self.current_page is not None:
            self.current_page.destroy()
        self.current_page = new_frame_cls()
        self.current_page.pack()

The difference between the two is that in the first case you're creating the pages at the start, and the second is that you're only creating the page when you are ready to show it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM