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
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.
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
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.