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

基于Tkinter的多窗口仪表盘导航类开发技术求助

问题描述

我正在开发一个Python项目,用Tkinter构建UI,通过Figma生成代码。目前已完成window_1和window_2两个窗口类,界面左侧设有仪表盘分区的菜单按钮。

遇到的问题:

  • 不知道如何定义类来管理多窗口导航(后续将扩展至5个窗口)
  • 希望点击菜单按钮切换窗口时,仅隐藏当前窗口而非删除其中的信息
  • 当前代码中window_structure类创建了一个Tk()实例,但窗口类内使用了.mainloop(),导致无法正确创建不直接打开的窗口实例
解决方案

核心思路

  1. 移除每个窗口类中的.mainloop(),仅在全局调用一次主窗口的.mainloop()
  2. 创建窗口管理器类,统一处理所有窗口的创建、显示与隐藏
  3. 切换窗口时使用window.withdraw()隐藏当前窗口,window.deiconify()显示目标窗口,保留窗口实例及其中的内容

修改后完整代码

from pathlib import Path
from tkinter import *
from tkinter import filedialog

class WindowStructure:
    def __init__(self):
        self.main_window = self.create_root()

    def upload_csv_file(self):
        self.filepath = filedialog.askopenfilename(filetypes=[("CSV files", "*.csv")])
        if self.filepath:
            print(f"已选择文件: {self.filepath}")
        else:
            print("未选择任何文件")

    def go_to_images_files(self, name_file: str, name_image: str) -> Path:
        return Path(__file__).parent / Path(name_file) / Path(name_image)
    
    def create_menu_buttons(self, name_file, window, switch_callback):
        # 按钮1:上传文件
        self.button_image_1 = PhotoImage(file=self.go_to_images_files(name_file, "button_1.png"))
        self.button_1 = Button(
            window,
            image=self.button_image_1,
            borderwidth=0,
            highlightthickness=0,
            command=self.upload_csv_file,
            relief="flat"
        )
        self.button_1.place(x=43.0, y=167.0, width=186.0, height=80.0)
    
        # 按钮2:切换到window_2
        self.button_image_2 = PhotoImage(file=self.go_to_images_files(name_file,"button_2.png"))
        self.button_2 = Button(
            window,
            image=self.button_image_2,
            borderwidth=0,
            highlightthickness=0,
            command=lambda: switch_callback("window_2"),
            relief="flat"
        )
        self.button_2.place(x=43.0, y=31.0, width=186.0, height=80.0)
        
        # 后续扩展按钮可在此添加
        
    def create_canvas(self, window, title):
        window.geometry("957x686")
        window.title(title)
        window.configure(bg="#189393")

        self.canvas = Canvas(
            window,
            bg="#189393",
            height=686,
            width=957,
            bd=0,
            highlightthickness=0,
            relief="ridge"
        )
        self.canvas.place(x=0, y=0)
        self.canvas.create_rectangle(
            0.0, 0.0, 271.0, 686.0,
            fill="#791010", outline=""
        )
        self.canvas.create_text(
            502.0, 14.0, anchor="nw",
            text="DASHBOARD", fill="#FFFFFF",
            font=("Inter Bold", 45 * -1)
        )
        return self.canvas
       
class BaseWindow:
    def __init__(self, parent, structure, title, name_file):
        self.window = Toplevel(parent)
        self.canvas = structure.create_canvas(self.window, title)
        self.name_file = name_file
        self.structure = structure
        self.create_content()
        self.window.resizable(False, False)
        self.window.withdraw()  # 初始隐藏,由管理器控制显示

    def create_content(self):
        pass  # 子类重写此方法实现自定义内容

class Window1(BaseWindow):
    def __init__(self, parent, structure, switch_callback):
        super().__init__(parent, structure, "UPLOAD", "WINDOW_1")
        self.structure.create_menu_buttons(self.name_file, self.window, switch_callback)

    def create_content(self):
        # 创建图片
        self.image_image_1 = PhotoImage(
            file=self.structure.go_to_images_files(self.name_file, "image_1.png"))
        self.image_1 = self.canvas.create_image(428.0, 205.0, image=self.image_image_1)
    
        # 创建输入框
        self.entry_image_1 = PhotoImage(
            file=self.structure.go_to_images_files(self.name_file,"entry_1.png"))
        self.entry_1 = Entry(bd=0, bg="#FFFFFF", fg="#000716", highlightthickness=0)
        self.entry_1.place(x=518.0, y=327.0, width=129.0, height=46.0)
        self.entry_bg_1 = self.canvas.create_image(582.5, 351.0, image=self.entry_image_1) 

class Window2(BaseWindow):
    def __init__(self, parent, structure, switch_callback):
        super().__init__(parent, structure, "FEUILLE 2", "WINDOW_2")
        self.structure.create_menu_buttons(self.name_file, self.window, switch_callback)

    def create_content(self):
        # 创建图片
        self.image_image_1 = PhotoImage(
            file=self.structure.go_to_images_files(self.name_file, "image_1.png"))
        self.image_1 = self.canvas.create_image(428.0, 205.0, image=self.image_image_1)
    
        # 创建输入框
        self.entry_image_1 = PhotoImage(
            file=self.structure.go_to_images_files(self.name_file,"entry_1.png"))
        self.entry_1 = Entry(bd=0, bg="#FFFFFF", fg="#000716", highlightthickness=0)
        self.entry_1.place(x=518.0, y=327.0, width=129.0, height=46.0)
        self.entry_bg_1 = self.canvas.create_image(582.5, 351.0, image=self.entry_image_1) 

class WindowManager:
    def __init__(self, structure):
        self.structure = structure
        self.current_window = None
        self.windows = {}
        
        self._init_windows()
        self.switch_window("window_1")  # 默认显示第一个窗口

    def _init_windows(self):
        self.windows["window_1"] = Window1(self.structure.main_window, self.structure, self.switch_window)
        self.windows["window_2"] = Window2(self.structure.main_window, self.structure, self.switch_window)
        # 扩展窗口时在此添加新实例

    def switch_window(self, window_name):
        if self.current_window is not None:
            self.current_window.window.withdraw()
        
        self.current_window = self.windows[window_name]
        self.current_window.window.deiconify()

# 程序入口
if __name__ == "__main__":
    interface_structure = WindowStructure()
    window_manager = WindowManager(interface_structure)
    interface_structure.main_window.mainloop()

代码说明

  1. WindowStructure:保留通用UI结构、菜单按钮、文件上传逻辑,菜单按钮新增切换回调参数
  2. BaseWindow:抽象基类,封装窗口通用初始化流程,子类只需实现自定义内容
  3. Window1/Window2:继承BaseWindow,实现各自UI内容,移除.mainloop()
  4. WindowManager:核心管理类,初始化所有窗口,通过withdraw()/deiconify()实现无状态丢失的窗口切换

内容的提问来源于stack exchange,提问作者Arnaud Patrick DA SILVA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:57:14