CustomTkinter:如何让PreferencesGUI嵌入主窗口而非打开新窗口?
解决CustomTkinter多类拆分后PreferencesGUI打开新窗口的问题
问题根源
你当前的PreferencesGUI继承了customtkinter.CTk,这会让它成为一个独立的顶层窗口,而非可嵌入主窗口的容器组件,因此调用时会弹出新窗口,无法嵌入baseSetup创建的主界面。
解决方案
通过以下步骤重构代码,让PreferencesGUI成为可嵌入的页面组件:
- 修改
PreferencesGUI的继承类:将其从CTk改为CTkFrame,使其成为可嵌入父容器的组件 - 在
baseSetup中添加主内容容器:预留一个区域用于切换显示不同页面(Home/Preferences等) - 实现页面切换逻辑:在主窗口内部处理按钮点击,将目标页面嵌入到主内容区域
修改后的完整代码示例
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
相关产品推荐
相关产品推荐

