0

Edited version:

I am new to Tkinter and would like to perform a page switching functionality similar to the answer to this question (Switch between two frames in tkinter?). However, rather than have all of my pages in one single .py file, I would like to call each of the pages from its own .py file.

The reason why I want this is that later I will have multiple sub-pages, which will each represent different tools.

My question is,

How can I still keep the same frame switching functionality while having each of my pages being called from different python files?

Here is what I have tried so far:

app.py

from page1 import *

import tkinter as tk
from tkinter import Tk, Frame, ttk
    

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

        # create a container for all the widgets (buttons, etc)
        container = 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 loops for switching between pages
        for F in (HomePage, PageOne, Tool1):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky="nsew")

        self.show_frame(HomePage)

    def show_frame(self, cont):
        frame = self.frames[cont]
        frame.tkraise()


class HomePage(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)

        label = ttk.Label(self, text="App Main Window", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

        proc_btn = ttk.Button(self, text="Go to Page One",
                              command=lambda: controller.show_frame(PageOne))
        proc_btn.pack(ipadx=5, ipady=5, expand=1)


if __name__ == "__main__":
    app = AppWindow()
    app.mainloop()

page1.py

from apptest import *

import tkinter as tk
from tkinter import Tk, Frame, ttk

class PageOne(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)

        label = ttk.Label(self, text="Page One !!!!!!!!", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

        proc1_btn = ttk.Button(self, text="Tool 1",
                               command=lambda: controller.show_frame(Tool1))
        proc1_btn.pack(ipadx=5, ipady=5, expand=1)

        home_btn = ttk.Button(self, text="Homepage",
                              command=lambda: controller.show_frame(HomePage))
        home_btn.pack(ipadx=5, ipady=5, expand=1)


class Tool1(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)

        label = ttk.Label(self, text="Tool 1 !!!!!!!!", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

        # Find what
        ttk.Label(self, text='Find:')
        keyword = ttk.Entry(self, width=30)
        keyword.focus()
        keyword.pack(ipadx=5, ipady=5, expand=1)

        # Replace with:
        ttk.Label(self, text='Replace:')
        replacement = ttk.Entry(self, width=30)
        replacement.pack(ipadx=5, ipady=5, expand=1)

        proc1_btn = ttk.Button(self, text="PageOne",
                               command=lambda: controller.show_frame(PageOne))
        proc1_btn.pack(ipadx=5, ipady=5, expand=1)

        home_btn = ttk.Button(self, text="Homepage",
                              command=lambda: controller.show_frame(HomePage))
        home_btn.pack(ipadx=5, ipady=5, expand=1)

My problem occurs when I try to use the "HomePage" button to go back to the HomePage when I am at the "PageOne" and "Tool1" pages. Here is the error that I am seeing.

Exception in Tkinter callback 
  Traceback (most recent call last):
     File "...\lib\tkinter\__init__.py", line 1705, in __call__ 
        return self.func(*args)   
     File "...\GUI\page1.py", line 21, in <lambda> 
        command=lambda: controller.show_frame(HomePage))
     File "C.../GUI/app.py", line 52, in show_frame 
        frame = self.frames[cont]

KeyError: <class 'apptest.HomePage'>

Thank you for your help in advance

Answer:

The answer to this question can be found here: Switch between two frames in tkinter in separates files

Toboggan
  • 37
  • 4
  • You've told us what you want, but you haven't asked a question. What's stopping you from doing what you want? Also, please try to reduce the code down to a [mcve]. If the question is about moving each page to a separate file, it doesn't really matter what's on each page. For this question, please create pages with just as few widgets as possible. – Bryan Oakley Apr 26 '22 at 19:25
  • Hi there, Thank you for your quick response and the suggestion. I have edited my question, it would be great if you could help me with this problem :D – Toboggan Apr 26 '22 at 20:26
  • Have you read this? https://stackoverflow.com/questions/39530107/tkinter-have-code-for-pages-in-separate-files – Bryan Oakley Apr 26 '22 at 20:50
  • Hi Bryan, Thank you for sharing the question, but unfortunately, that question was not exactly addressed my problem. Tho, I found another question that is closer to my problem, which you actually answered too. https://stackoverflow.com/questions/67992255/switch-between-two-frames-in-tkinter-in-separates-files – Toboggan Apr 26 '22 at 21:55

1 Answers1

0

Edit: Didn't not read on p2.py

You cannot call app.py to page1.py, because app.py is the app.py way to start.

How can I still keep the same frame switching functionality while having each of my pages being called from different python files?

You have 2 missing on Label widget pack, grid or place. page1.py` module. See on screenshot.

  • In app.py, copy and remove the Class HomePage to page1.py module.
  • In page1 module. line 44 add pack() to ttk.Label(self, text='Find:').pack()
  • In page1 module. line 44 add pack()tottk.Label(self, text='Replace:').pack()`
  • I commented out from apptest import *. Actually, I don't know what it is.
  • In page1 module, you are missing constant LARGE_FONT. I added this LARGE_FONT = "Arial", 25 just in case.

Code on page1.py:

LARGE_FONT = "Arial", 25

class HomePage(Frame):
    def __init__(self, parent, controller):
        Frame.__init__(self, parent)

        label = ttk.Label(self, text="App Main Window", font=LARGE_FONT)
        label.pack(pady=10, padx=10)

        proc_btn = ttk.Button(self, text="Go to Page One",
                              command=lambda: controller.show_frame(PageOne))
        proc_btn.pack(ipadx=5, ipady=5, expand=1)


class PageOne(Frame):
...
...

Screenshot:

enter image description here

toyota Supra
  • 3,181
  • 4
  • 15
  • 19