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

CustomTkinter:如何让PreferencesGUI嵌入主窗口而非打开新窗口?

解决CustomTkinter多类拆分后PreferencesGUI打开新窗口的问题

问题根源

你当前的PreferencesGUI继承了customtkinter.CTk,这会让它成为一个独立的顶层窗口,而非可嵌入主窗口的容器组件,因此调用时会弹出新窗口,无法嵌入baseSetup创建的主界面。

解决方案

通过以下步骤重构代码,让PreferencesGUI成为可嵌入的页面组件:

  1. 修改PreferencesGUI的继承类:将其从CTk改为CTkFrame,使其成为可嵌入父容器的组件
  2. 在baseSetup中添加主内容容器:预留一个区域用于切换显示不同页面(Home/Preferences等)
  3. 实现页面切换逻辑:在主窗口内部处理按钮点击,将目标页面嵌入到主内容区域

修改后的完整代码示例

import customtkinter

class baseSetup(customtkinter.CTk):
    def __init__(self):
        super().__init__()

        # MAIN SETUP
        self.title("Recs")
        self.geometry("898x506")
        
        self.grid_columnconfigure(0, weight=0)
        self.grid_columnconfigure(1, weight=1)
        self.grid_rowconfigure(0, weight=1)

        # 左侧菜单面板
        self.frameLeft = customtkinter.CTkFrame(self, width=140, corner_radius=0)
        self.frameLeft.grid(row=0, column=0, sticky="nsew")
        self.frameLeft.grid_rowconfigure(4, weight=1)
        
        self.frameLeftMenuTitle = customtkinter.CTkLabel(self.frameLeft, text="TITLE", font=("Arial", 40))
        self.frameLeftMenuTitle.grid(row=0, column=0, padx=20, pady=(20, 10))

        self.frameLeftHomeButton = customtkinter.CTkButton(self.frameLeft, text="Home", font=("Arial",16), command=self.show_home)
        self.frameLeftHomeButton.grid(row=1, column=0, padx=30, pady=(20, 10))

        self.frameLeftPreferencesButton = customtkinter.CTkButton(self.frameLeft, text="Preferences", font=("Arial",16), command=self.show_preferences)
        self.frameLeftPreferencesButton.grid(row=2, column=0, padx=30, pady=(20, 10))

        self.frameLeftInfoButton = customtkinter.CTkButton(self.frameLeft, text="Info", font=("Arial",16), command=self.show_info)
        self.frameLeftInfoButton.grid(row=3, column=0, padx=30, pady=(20, 10))

        self.frameLeftAccountButton = customtkinter.CTkButton(self.frameLeft, text="Account", font=("Arial",16), command=self.show_account)
        self.frameLeftAccountButton.grid(row=4, column=0, padx=30, pady=(20, 10), sticky="new")

        # 主内容区域:用于切换显示不同页面
        self.main_content_frame = customtkinter.CTkFrame(self, corner_radius=0, fg_color="transparent")
        self.main_content_frame.grid(row=0, column=1, sticky="nsew")
        self.main_content_frame.grid_rowconfigure(0, weight=1)
        self.main_content_frame.grid_columnconfigure(0, weight=1)

        # 默认显示Home页面
        self.show_home()

        self.mainloop()

    def clear_content(self):
        # 清空主内容区域的所有组件
        for widget in self.main_content_frame.winfo_children():
            widget.destroy()

    def show_home(self):
        self.clear_content()
        home_label = customtkinter.CTkLabel(self.main_content_frame, text="Home Page", font=("Arial", 30))
        home_label.grid(row=0, column=0, padx=20, pady=20)

    def show_preferences(self):
        self.clear_content()
        # 创建PreferencesGUI实例并嵌入主内容区域
        self.preferences_page = PreferencesGUI(self.main_content_frame)
        self.preferences_page.grid(row=0, column=0, sticky="nsew")

    def show_info(self):
        self.clear_content()
        info_label = customtkinter.CTkLabel(self.main_content_frame, text="Info Page", font=("Arial", 30))
        info_label.grid(row=0, column=0, padx=20, pady=20)

    def show_account(self):
        self.clear_content()
        account_label = customtkinter.CTkLabel(self.main_content_frame, text="Account Page", font=("Arial", 30))
        account_label.grid(row=0, column=0, padx=20, pady=20)


class PreferencesGUI(customtkinter.CTkFrame):
    def __init__(self, parent):
        super().__init__(parent)   

        # 配置当前Frame的布局权重
        self.grid_rowconfigure(0, weight=1)
        self.grid_columnconfigure(0, weight=1)

        # 创建滚动容器
        self.frameMaster = customtkinter.CTkScrollableFrame(self, width=675, corner_radius=0, fg_color="transparent")
        self.frameMaster.grid(row=0, column=0, sticky="nsew")
        self.frameMaster.grid_rowconfigure(0, weight=1)
        self.frameMaster.grid_columnconfigure(0, weight=1)

        # 顶部标题框架
        self.frameMiddle = customtkinter.CTkFrame(self.frameMaster, corner_radius=10)
        self.frameMiddle.grid(row=0, column=0, padx=(10,10), pady=(10,10), sticky="nsew")
        
        self.frameMiddleTitle = customtkinter.CTkLabel(self.frameMiddle, text="Preferences", font=("Arial", 40))
        self.frameMiddleTitle.grid(row=0, column=0, padx=150, pady=(10, 10))

        # 示例滑块(可继续添加其他偏好设置组件)
        slider = customtkinter.CTkSlider(self.frameMaster, from_=0, to=100)
        slider.grid(row=1, column=0, padx=20, pady=20, sticky="ew")


if __name__ == "__main__":
    app = baseSetup()

关键修改说明

  • 页面类继承调整:PreferencesGUI改为继承CTkFrame,不再创建独立窗口,而是作为子组件嵌入父容器
  • 主内容区域预留:baseSetup中新增main_content_frame,统一管理所有页面的显示
  • 页面切换逻辑:通过clear_content方法清空旧页面,再创建新页面实例并布局,避免组件叠加
  • 回调函数内聚:将按钮的回调改为baseSetup内部方法,统一处理页面切换,便于后续扩展

内容的提问来源于stack exchange,提问作者char_par

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:44:57