Tkinter中Canvas层级遮挡Frame显示及非按钮触发页面切换问题
问题现象:Canvas出现在置于顶层的Frame上方
背景说明
使用了某网站的顶部模板仅做少量修改,程序启动时应当展示StartPage,代码如下:
class StartPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller def check_user_login(): # 已省略根据输入框内容更新Canvas元素的代码 if un == True and pw == True: print("Login verified") app().show_frame("PageOne") # 该行代码不生效,需要实现无需按钮即可触发页面切换的方案 return None # 创建用于放置图片的Canvas canvas = Canvas(self.controller, bg = "#5c5c5c",height = 400,width = 800,bd = 0,highlightthickness = 0,relief = "flat") canvas.place(x = 0, y = 0) # 已省略部分冗余代码 # 顶部输入框 un_img = PhotoImage(file = f"img_textBox0.png") un_bg = canvas.create_image(400.0, 200.0, image=un_img, tags="username_box") un_input = Entry(bd = 0, bg = "#5c5c5c") un_input.place(x = 310.0, y = 189,width = 180.0,height = 21) # 背景图 background_img = PhotoImage(file = f"background.png") background = canvas.create_image(371.5, 185.5, image=background_img) # 登录按钮 login_button_img = PhotoImage(file = f"img0.png") b0 = Button(image = login_button_img, borderwidth = 0, highlightthickness = 0, command = check_user_login, relief = "flat") b0.place(x = 356, y = 290,width = 89,height = 29) # 图片引用持有,避免被GC回收 self.background_img = background_img self.un_img = un_img self.login_button_img = login_button_img self.ip_red = ip_red
按逻辑StartPage应当置于窗口最上层,但实际只有下层Frame的Canvas可见,删除下方PageOne的Canvas后,StartPage的内容即可正常显示。PageOne代码如下:
class PageOne(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller
此外登录校验逻辑中调用切换到PageOne的代码无法生效,需要实现无需按钮即可触发页面切换的方案。
修复方案
1. 层级错乱问题修复
- 原因:创建Canvas时父容器指定了
self.controller(主窗口对象),而非当前StartPage实例,因此Canvas不受Frame的层级控制,会直接固定在主窗口最上层,覆盖所有Frame的内容。 - 修复方法:将Canvas创建代码的父参数改为当前Frame实例:
把canvas = Canvas(self.controller, bg = "#5c5c5c",height = 400,width = 800,bd = 0,highlightthickness = 0,relief = "flat")
修改为canvas = Canvas(self, bg = "#5c5c5c",height = 400,width = 800,bd = 0,highlightthickness = 0,relief = "flat")
2. 页面切换不生效问题修复
- 原因:原代码中
app().show_frame("PageOne")是重新实例化了一个新的主程序对象,并非当前正在运行的窗口实例,因此不会触发当前窗口的页面切换。 - 修复方法:直接使用初始化时传入的当前运行的主程序实例调用切换方法,将切换代码修改为
self.controller.show_frame("PageOne")即可。
如果需要实现无需按钮触发切换,只需要在对应校验逻辑(比如定时校验、输入实时校验等)的位置直接调用上述切换代码即可,不需要绑定按钮触发。
内容的提问来源于stack exchange,提问作者Will Jordan
相关产品推荐
相关产品推荐

