0

as a Python / tkinter beginner, I have kind of encountered a problem that I could not solve by myself. Any help of you would be greatly appreciated - thank you in advance!

I am trying to create a GUI with tkinter where the user can switch between different windows / frames by pressing a button. By reading through the already existing stack overflow questions, I have seen that many users suggest an object - oriented approach to a GUI. Therefore, I have tried a draft for this specific purpose by the user @Bryan Oakley - link to the original question: Switch between two frames in tkinter In this code, all pages that are to be seen and accessed by the user are defined as separate classes and 'stored' in the container frame. So whenever a specific frame should become visible, the function show_frame raises it above the others.

My question: I would like to assign individual static window sizes to the displayed frames StartPage, PageOne etc. For instance, PageOne is the frame where the user will work on and should thus be bigger than the StartPage that just functions as a menu. Nevertheless, when searching through the internet, I can only find the option how to make them all equally big, by saying app.geometry(' <entered_geometry>'). Sadly, this does not solve my problem.

I have already tried a lot, but, as I stated above, I am a beginner and still have to kind of wrap my head around tkinter with a OOP approach. I hope that I was able to explain the issue properly. Again, I would be very thankful if any of you could please help me as desperation has already begun to take over haha :)

try:
    import tkinter as tk                # python 3
    from tkinter import font as tkfont  # python 3
except ImportError:
    import Tkinter as tk     # python 2
    import tkFont as tkfont  # python 2

class SampleApp(tk.Tk):

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

        self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")

        # the container is where we'll stack a bunch of frames
        # on top of each other, then the one we want visible
        # will be raised above the others
        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):
            page_name = F.__name__
            frame = F(parent=container, controller=self)
            self.frames[page_name] = frame

            # put all of the pages in the same location;
            # the one on the top of the stacking order
            # will be the one that is visible.
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame("StartPage")

    def show_frame(self, page_name):
        '''Show a frame for the given page name'''
        frame = self.frames[page_name]
        frame.tkraise()


class StartPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is the start page", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)

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


class PageOne(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is page 1", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to the start page",
                           command=lambda: controller.show_frame("StartPage"))
        button.pack()


class PageTwo(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller
        label = tk.Label(self, text="This is page 2", font=controller.title_font)
        label.pack(side="top", fill="x", pady=10)
        button = tk.Button(self, text="Go to the start page",
                           command=lambda: controller.show_frame("StartPage"))
        button.pack()


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()
Alles Klar
  • 31
  • 4
  • 1
    The *whole point* of the approach you've linked to is that all of the individual pages exist from the beginning, so the window automatically adopts a fixed size that's large enough to hold any of the pages without resizing. Other than that, the approach is problematic - entry fields on non-current pages are still active, and you can accidentally type into them. For your needs, you don't want all of the pages to exist at the same time; instead of raising one to show it, `.grid()` it, and `grid_forget()` the rest. – jasonharper Apr 14 '21 at 17:48
  • Yeah, that code is definitely not good for a beginner. I hate that I wrote that code, it was definitely not designed to be a general purpose solution used by beginners. :-\ – Bryan Oakley Apr 14 '21 at 17:51
  • @BryanOakley I was thankfull as I found that code, even if I didnt understand it at the time. It gives even beginners space to code some apllications. Im not sure if I would still be coding if I hadnt that much fun with that piece of code. So thank you :) – Thingamabobs Apr 14 '21 at 18:53
  • @jasonharper Thank you for your advice! The problem is that I have received a code from another person that I should finish. This person has already defined the very specific positions of every widget with .place(relx, rely). Sadly, by experimenting, I have seen that your method only works if I use .grid() all the time. Is there a way to still use .place and get the frame to automatically resize in relation to my outputtet widgets? – Alles Klar Apr 16 '21 at 15:54

0 Answers0