You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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内容。

实现思路

  1. 主应用类统一管理主窗口和所有页面实例
  2. 每个页面封装为tk.Frame子类,负责自身UI元素创建
  3. 页面切换时,隐藏当前页面的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 07:15:37