如何在Tkinter多模块页面切换时复用同一窗口?
Tkinter实现单窗口页面切换(解决每次切换开新窗口问题)
我用Tkinter开发多模块应用,每个模块对应一个独立页面,但点击「开始页面」「返回」按钮时每次都会打开新窗口,如何让页面始终在同一窗口显示?原代码如下:
task1.py
import tkinter as tk from Test.modul.task1 import FirstPage1 class FirstPage0: def __init__(self, root): self.root = root def get_settings(self): # Window settings self.root.geometry("100x200") def get_second_page(self): FirstPage1(tk.Toplevel()).get_run_first_page() def get_button(self): # Add buttons tk.Button(self.root, text="Start page", command=self.get_second_page).pack() tk.Button(self.root, text="Exit", command=self.root.destroy).pack() def get_run_first_page(self): # Launching the application self.get_settings() self.get_button() self.root.mainloop() if __name__ == '__main__': first = FirstPage0(tk.Tk()) first.get_run_first_page()
task2.py
import tkinter as tk class FirstPage1: def __init__(self, root): self.root = root def get_settings(self): # Window settings self.root.geometry("100x200") def get_second_page1(self): from Test.task import FirstPage0 FirstPage0(tk.Toplevel()).get_run_first_page() def get_button(self): # Add buttons tk.Button(self.root, text="Back", command=self.get_second_page1).pack() tk.Button(self.root, text="Exit", command=self.root.destroy).pack() def get_run_first_page(self): # Launching the application self.get_settings() self.get_button() self.root.mainloop() if __name__ == '__main__': first = FirstPage1(tk.Tk()) first.get_run_first_page()
解决方案
问题根源是每次切换页面时创建了新窗口实例(tk.Toplevel()),且每个页面都单独调用mainloop(),导致多窗口和多事件循环冲突。正确做法是用单个主窗口,以Frame作为页面容器,切换时仅替换Frame内容。
实现思路
- 主应用类统一管理主窗口和所有页面实例
- 每个页面封装为
tk.Frame子类,负责自身UI元素创建 - 页面切换时,隐藏当前页面的Frame,显示目标页面的Frame,无需新建窗口
修改后的代码示例
主入口文件(app.py)
import tkinter as tk from task1 import FirstPage0 from task2 import FirstPage1 class App: def __init__(self, root): self.root = root self.root.geometry("100x200") # 存储所有页面实例 self.pages = {} # 初始化页面,传入切换方法 self.pages["FirstPage0"] = FirstPage0(self.root, self.switch_page) self.pages["FirstPage1"] = FirstPage1(self.root, self.switch_page) # 默认显示初始页面 self.current_page = None self.switch_page("FirstPage0") def switch_page(self, page_name): # 隐藏当前页面 if self.current_page is not None: self.current_page.pack_forget() # 显示目标页面 self.current_page = self.pages[page_name] self.current_page.pack(fill="both", expand=True) if __name__ == '__main__': root = tk.Tk() app = App(root) root.mainloop()
task1.py
import tkinter as tk class FirstPage0(tk.Frame): def __init__(self, parent, switch_page): super().__init__(parent) self.switch_page = switch_page self.create_widgets() def create_widgets(self): tk.Button(self, text="Start page", command=lambda: self.switch_page("FirstPage1")).pack() tk.Button(self, text="Exit", command=self.master.destroy).pack()
task2.py
import tkinter as tk class FirstPage1(tk.Frame): def __init__(self, parent, switch_page): super().__init__(parent) self.switch_page = switch_page self.create_widgets() def create_widgets(self): tk.Button(self, text="Back", command=lambda: self.switch_page("FirstPage0")).pack() tk.Button(self, text="Exit", command=self.master.destroy).pack()
关键修改说明
- 移除所有
tk.Toplevel()创建逻辑,所有页面共享同一个主窗口 - 每个页面改为继承
tk.Frame,不再单独调用mainloop(),整个应用仅保留主窗口的一个事件循环 - 通过
pack_forget()隐藏当前页面、pack()显示目标页面,实现无刷新切换 - 主应用类统一管理页面切换,避免模块间循环导入问题
内容的提问来源于stack exchange,提问作者Adrian Sz
相关产品推荐
相关产品推荐

