Navigating between tkinter frames in multiple modules

Question:

I’m new to Python. Trying to create two modules (.py files) which can be navigated to & fro, without having to create two windows. So, 1st module will have window & frame 1, 2nd module will have just a frame 2. On button click, the frame shown should be switched. Not sure if the below is the right way to do it, but I’m almost there. If there’s a better way to do this, please suggest. testnew.py –

from tkinter import *
from functools import partial

BLACK = "#000000"
WHITE = "#FFFFFF"


class main():
    def __init__(self, master):
        self.frame1 = Frame(master)
        self.frame1.pack()

        self.label = Label(self.frame1, bg=WHITE, text="This is 1st frame.")
        self.label.pack()

        self.btn_1 = Button(self.frame1, bg=WHITE, text="Switch to 2nd frame",
                            command=partial(self.switch_to_second, master))
        self.btn_1.pack()

    def switch_to_second(self, master):
        self.btn_1.pack_forget()
        self.label.pack_forget()
        self.frame1.pack_forget()
        from testnew_2 import second_frame
        self.secondframe = second_frame(master)


root = Tk()
root.title("Hello world")
root.geometry("500x500")
main_frame = main(root)
root.mainloop()

testnew_2.py –

from tkinter import *
from functools import partial

BLACK = "#000000"
WHITE = "#FFFFFF"


class second_frame():
    def __init__(self, master):
        self.frame2 = Frame(master)
        self.frame2.pack()

        self.label2 = Label(self.frame2, bg=BLACK, fg=WHITE, text="This is second frame.")
        self.label2.pack()

        self.btn_2 = Button(self.frame2, bg=BLACK, fg=WHITE, text="Switch to 1st frame",
                            command=partial(self.switch_to_first, master))
        self.btn_2.pack()

    def switch_to_first(self, master):
        self.btn_2.pack_forget()
        self.label2.pack_forget()
        self.frame2.pack_forget()
        from testnew import main
        self.mainframe = main(master)

Running into a problem of another window being created + this error –

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:UsersAdminAppDataLocalProgramsPythonPython311Libtkinter__init__.py", line 1948, in __call__
    return self.func(*args)
           ^^^^^^^^^^^^^^^^
  File "C:UsersAdminPycharmProjectshelloworldtestnew_2.py", line 25, in switch_to_first
    self.mainframe = main(master)
                     ^^^^^^^^^^^^
  File "C:UsersAdminPycharmProjectshelloworldtestnew.py", line 10, in __init__
    self.frame1 = Frame(master)
                  ^^^^^^^^^^^^^
  File "C:UsersAdminAppDataLocalProgramsPythonPython311Libtkinter__init__.py", line 3180, in __init__
    Widget.__init__(self, master, 'frame', cnf, {}, extra)
  File "C:UsersAdminAppDataLocalProgramsPythonPython311Libtkinter__init__.py", line 2628, in __init__
    self.tk.call(
_tkinter.TclError: can't invoke "frame" command: application has been destroyed

Asked By: Ace

||

Answers:

When testnew is imported inside switch_to_first(), the following code inside testnew.py will be executed again to create another instance of Tk():

root = Tk()
root.title("Hello world")
root.geometry("500x500")
main_frame = main(root)
root.mainloop()

So there will be two windows shown. The mentioned exception will be raised when the two windows are closed.

You need to change the above code block as below:

if __name__ == "__main__":
    root = Tk()
    root.title("Hello world")
    root.geometry("500x500")
    main_frame = main(root)
    root.mainloop()

Then when testnew is imported again, no new window will be created because code inside the if block will not be executed.

Answered By: acw1668
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.