I've created a tkinter app, which has three pages: StartPage, PageOne and PageTwo. From StartPage you can go to PageOne and to PageTwo, whereas from PageOne and PageTwo, you can go back to StartPage. To implement it, I am using the technique described by Steven Vascellaro in this post Switch between two frames in tkinter.
This is the code provided by Steven:
# Multi-frame tkinter application v2.2
import tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
start_label = tk.Label(self, text="This is the start page")
page_1_button = tk.Button(self, text="Open page one",
command=lambda: master.switch_frame(PageOne))
page_2_button = tk.Button(self, text="Open page two",
command=lambda: master.switch_frame(PageTwo))
start_label.pack(side="top", fill="x", pady=10)
page_1_button.pack()
page_2_button.pack()
class PageOne(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
page_1_label = tk.Label(self, text="This is page one")
start_button = tk.Button(self, text="Return to start page",
command=lambda: master.switch_frame(StartPage))
page_1_label.pack(side="top", fill="x", pady=10)
start_button.pack()
class PageTwo(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
page_2_label = tk.Label(self, text="This is page two")
start_button = tk.Button(self, text="Return to start page",
command=lambda: master.switch_frame(StartPage))
page_2_label.pack(side="top", fill="x", pady=10)
start_button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
Now, I am trying to make this code modular and place each page in a separate python file. This is how I split the Steven's code between three Python files (start_page.py, page_one.py, page_two.py):
start_page.py:
import tkinter as tk
from page_one import PageOne
from page_two import PageTwo
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
start_label = tk.Label(self, text="This is the start page")
page_1_button = tk.Button(self, text="Open page one",
command=lambda: master.switch_frame(PageOne))
page_2_button = tk.Button(self, text="Open page two",
command=lambda: master.switch_frame(PageTwo))
start_label.pack(side="top", fill="x", pady=10)
page_1_button.pack()
page_2_button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
page_one.py:
import tkinter as tk
from start_page import StartPage
class PageOne(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
page_1_label = tk.Label(self, text="This is page one")
start_button = tk.Button(self, text="Return to start page",
command=lambda: master.switch_frame(StartPage))
page_1_label.pack(side="top", fill="x", pady=10)
start_button.pack()
page_two.py:
import tkinter as tk
from start_page import StartPage
class PageTwo(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
page_2_label = tk.Label(self, text="This is page two")
start_button = tk.Button(self, text="Return to start page",
command=lambda: master.switch_frame(StartPage))
page_2_label.pack(side="top", fill="x", pady=10)
start_button.pack()
The problem is here the class StartPage depends on PageOne and PageTwo, while PageOne and PageTwo depend on StartPage. This leads to the error described in this post ImportError: Cannot import name X.
Is there a way in tkinter to keep the described functionality, but to allow each page to be located in a separate python file?