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

如何在子框架及内嵌Menu类中调用父类show_frame实现框架切换?

解决CTk框架内嵌Menu的页面切换问题

问题核心

Menu类作为LoginFrame、RegEmailFrame的子组件,无法直接访问顶层窗口的show_frame方法导致切换功能失效,且不想在实例化Menu时手动传递controller参数。

简便解决方案

利用Tkinter组件的winfo_toplevel()方法直接获取顶层窗口实例(即Login_Window对象),无需手动传参,同时修正原代码中的语法错误:

修改后的完整代码

import tkinter as tk
import customtkinter as ctk

class Login_Window(ctk.CTk):
    def __init__(self, *args, **kwargs):
        super().__init__()

        self.geometry('400x400')
        self.title('Music Mayhem')
        self.resizable(False, False)

        container = ctk.CTkFrame(master=self)
        container.pack(side='top', fill='both', expand=True)
        
        container.grid_rowconfigure(0, weight=1)
        container.grid_columnconfigure(0, weight=1)

        self.frames={}

        for F in (LoginFrame, RegEmailFrame):
            frame = F(container, self)
            self.frames[F] = frame
            frame.grid(row=0, column=0, sticky= 'nsew')
            frame.grid_columnconfigure(0,weight=1)
            frame.grid_rowconfigure(0,weight=1)
             

        self.show_frame(LoginFrame) 

    def show_frame(self, cont):
        frame = self.frames[cont] 
        frame.tkraise()

class LoginFrame (tk.Frame):
    def __init__(self,parent, controller):
        tk.Frame.__init__(self, parent)

        self.menu = Menu(self)
        self.menu.grid(row=0, column=0) 

        # 修正括号闭合问题
        self.loginBtn = ctk.CTkButton(master=self, width=100, height = 20,text='跳转到注册', 
                                state='normal',
                                command=lambda: controller.show_frame(RegEmailFrame))
        self.loginBtn.grid(row=1, column=0)

class RegEmailFrame(tk.Frame):
    def __init__(self, parent, controller,header_name="Register Email"):
        tk.Frame.__init__(self, parent)

        self.menu = Menu(self)
        self.menu.grid(row=0, column=0)
    
        # 修正拼写错误和参数逗号
        self.emailLabel = ctk.CTkLabel(master=self,width=100, height=20, text='已切换到注册页') 
        self.emailLabel.grid(row=1, column=0) 

class Menu(tk.Frame):  
    def __init__(self, *args, header_name="Logo Frame",
                 width=175, height=175,**kwargs):
        super().__init__(*args, width=width, height=height, **kwargs)

        # 通过winfo_toplevel()获取顶层窗口(Login_Window实例)
        self.menuloginBtn = ctk.CTkButton(master=self, width=100, height = 20,text='登录页', 
                                state='normal',
                                command=lambda: self.winfo_toplevel().show_frame(LoginFrame))
        self.menuloginBtn.grid(row=0, column=0)

        # 修正按钮文本和括号
        self.menuRegBtn = ctk.CTkButton(master=self, width=100, height = 20,text='注册页', 
                                state='normal',
                                command=lambda: self.winfo_toplevel().show_frame(RegEmailFrame))
        self.menuRegBtn.grid(row=1, column=0)

if __name__ == "__main__":
    app = Login_Window()
    app.mainloop()

关键说明

  • self.winfo_toplevel()会返回当前组件所在的顶层窗口对象(即Login_Window实例),它自带show_frame方法,直接调用即可实现页面切换。
  • 无需修改LoginFrame和RegEmailFrame的实例化逻辑,也不需要手动给Menu传递controller参数,完全自动获取顶层控制器。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 10:50:39