0

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'

  • 1
    `to_add.pack()` requires a reference on the left side but you use `.switch_frames(..., SecondaryPage)` a class definiton. Does this answer your question? [TypeError: Missing one required positional argument](https://stackoverflow.com/a/50594457/7414759) – stovfl Jun 20 '20 at 15:08
  • Thanks! replaced SecondaryPage with SecondaryPage() and it works. –  Jun 20 '20 at 17:09
  • ***replaced SecondaryPage with `SecondaryPage()`***: Are you aware, that you create a new `SecondaryPage()` object at every click of `.Button(self, text="Switch to SecondaryPage"...)` Read up on [Tkinter.Pack.pack_forget-method](http://effbot.org/tkinterbook/pack.htm#Tkinter.Pack.pack_forget-method) and [Stack Frames on top of each other](https://stackoverflow.com/a/7557028/7414759) – stovfl Jun 20 '20 at 17:29

1 Answers1

0

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.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685