如何在子框架及内嵌Menu类中调用父类show_frame实现框架切换?
问题核心
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
相关产品推荐
相关产品推荐

