Tkinter框架切换故障:button_5无法跳转至PageOne
问题描述
使用Tkinter-Designer将Figma框架转换为Python代码并整合到StartPage类中,参考框架切换的实现代码后,点击button_5无法跳转至PageOne,无任何视觉反馈。本人不熟悉OOP,求定位问题原因。
完整代码如下:
import tkinter as tk # python 3 from tkinter import font as tkfont # python 3 from pathlib import Path OUTPUT_PATH = Path(__file__).parent ASSETS_PATH = OUTPUT_PATH / Path(r"Z:\python\projects\v\code\gui\tmp\TkinterDesigner\build\assets\frame0") def relative_to_assets(path: str) -> Path: return ASSETS_PATH / Path(path) class SampleApp(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self, *args, **kwargs) self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic") # the container is where we'll stack a bunch of frames # on top of each other, then the one we want visible # will be raised above the others container = tk.Frame(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 (StartPage, PageOne, PageTwo): page_name = F.__name__ frame = F(parent=container, controller=self) self.frames[page_name] = frame # put all of the pages in the same location; # the one on the top of the stacking order # will be the one that is visible. frame.grid(row=0, column=0, sticky="nsew") self.show_frame("StartPage") def show_frame(self, page_name): '''Show a frame for the given page name''' frame = self.frames[page_name] frame.tkraise() class StartPage(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller canvas = tk.Canvas( bg="#FFFFFF", height=724, width=1056, bd=0, highlightthickness=0, relief="ridge" ) canvas.place(x=0, y=0) canvas.create_rectangle( 56.0, 68.0, 954.0, 673.0, fill="#F2F2F2", outline="") canvas.create_rectangle( 56.0, 68.0, 285.0, 673.0, fill="#D4D3D3", outline="") self.button_image_1 = tk.PhotoImage( file=relative_to_assets("button_1.png")) button_1 = tk.Button( image=self.button_image_1, borderwidth=0, highlightthickness=0, command=lambda: print("button_1 clicked"), relief="flat" ) button_1.place( x=56.0, y=348.0, width=229.0, height=37.0 ) self.button_image_2 = tk.PhotoImage( file=relative_to_assets("button_2.png")) button_2 = tk.Button( image=self.button_image_2, borderwidth=0, highlightthickness=0, command=lambda: print("button_2 clicked"), relief="flat" ) button_2.place( x=56.0, y=312.0, width=229.0, height=37.0 ) self.button_image_3 = tk.PhotoImage( file=relative_to_assets("button_3.png")) button_3 = tk.Button( image=self.button_image_3, borderwidth=0, highlightthickness=0, command=lambda: print("button_3 clicked"), relief="flat" ) button_3.place( x=56.0, y=274.0, width=229.0, height=36.0 ) self.button_image_4 = tk.PhotoImage( file=relative_to_assets("button_4.png")) button_4 = tk.Button( image=self.button_image_4, borderwidth=0, highlightthickness=0, command=lambda: print("button_4 clicked"), relief="flat" ) button_4.place( x=56.0, y=239.0, width=229.0, height=36.0 ) self.button_image_5 = tk.PhotoImage( file=relative_to_assets("button_5.png")) button_5 = tk.Button( image=self.button_image_5, borderwidth=0, highlightthickness=0, command=lambda: controller.show_frame("PageOne"), relief="flat" ) button_5.place( x=56.0, y=201.0, width=229.0, height=37.0 ) self.image_image_1 = tk.PhotoImage( file=relative_to_assets("image_1.png")) image_1 = canvas.create_image( 617.0, 300.0, image=self.image_image_1 ) canvas.create_text( 706.0, 574.0, anchor="nw", text=" -Jim Rohn", fill="#000000", font=("RobotoMono Regular", 14 * -1) ) canvas.create_text( 433.0, 500.0, anchor="nw", text="“Reading is essential for those who seek to rise above the ordinary.” ", fill="#000000", font=("RobotoMono Regular", 14 * -1) ) canvas.create_text( 84.0, 100.0, anchor="nw", text="Hello ZZZ!", fill="#000000", font=("RobotoMono Bold", 18 * -1) ) class PageOne(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller label = tk.Label(self, text="This is page 1", font=controller.title_font) label.pack(side="top", fill="x", pady=10) button = tk.Button(self, text="Go to the start page", command=lambda: controller.show_frame("StartPage")) button.pack() class PageTwo(tk.Frame): def __init__(self, parent, controller): tk.Frame.__init__(self, parent) self.controller = controller label = tk.Label(self, text="This is page 2", font=controller.title_font) label.pack(side="top", fill="x", pady=10) button = tk.Button(self, text="Go to the start page", command=lambda: controller.show_frame("StartPage")) button.pack() if __name__ == "__main__": app = SampleApp() app.geometry("1056x724") app.configure(bg="#FFFFFF") app.mainloop()
问题原因
button_5的点击逻辑本身没有问题,框架切换操作已经执行了,但**StartPage中的Canvas使用了place(x=0, y=0)绝对定位,它会脱离StartPage的布局层级,直接显示在主窗口的最上层**,导致切换后的PageOne被这个Canvas遮挡,视觉上看不到变化。
修复方案
将Canvas的布局方式从place改为pack,让它作为StartPage的子组件,跟随StartPage的显示/隐藏一起变化:
修改StartPage类中Canvas的布局代码:
# 替换原来的 canvas.place(x=0, y=0) canvas.pack(fill="both", expand=True)
同时,移除Canvas的固定宽高设置,让它自动适配StartPage的大小(可选,让布局更灵活):
canvas = tk.Canvas( self, bg="#FFFFFF", # 移除固定height和width bd=0, highlightthickness=0, relief="ridge" )
修改后,StartPage的Canvas会作为Frame的一部分,当切换到PageOne时,StartPage被隐藏,Canvas也会跟着隐藏,PageOne的内容就能正常显示了。
内容的提问来源于stack exchange,提问作者ZZZ
相关产品推荐
相关产品推荐

