Tkinter界面切换异常:frame.pack_forget()仅生效一次
问题原因
你遇到的界面只能切换一次的问题,根源在于:
- 初始化时定义的全局
frame,在carr()、cerc()等函数里被重新定义成了局部变量,导致全局的frame引用被覆盖。 - 菜单命令里的
frame.pack_forget()只能操作最初的全局框架,第一次点击后这个框架已经被隐藏,但后续显示的是函数里新建的局部框架,你没有对这些新框架做隐藏操作,所以再次点击菜单时无法切换。
解决方案
复用全局的frame,每次切换界面时先清空框架内的所有组件,再添加对应模块的新内容。这样不需要反复创建新框架,也能保证每次操作的都是同一个框架对象。
修改后的完整代码
from tkinter import * from tkinter import messagebox # 初始化主窗口 fenetre = Tk() fenetre.title("Application d'aide en géométrie") fenetre.geometry("700x720") fenetre.iconbitmap("logo.ico") fenetre.config(background="#03EFFA") # 创建全局主框架 frame = Frame(fenetre, bg="#03EFFA") # 初始界面内容 def init_interface(): text1 = Label(frame, text="Bienvenue sur ce module d'aide en géométrie !", font=("Courrier", 20), bg="#03EFFA", fg="white") text2 = Label(frame, text="À l'aide du menu de séléction, vous pourrez accèder à différentes fonctions vous \n permettant de calculer aire et périmètre de différentes figures géométriques.", font=("Courrier", 13), bg="#03EFFA", fg="white") text3 = Label(frame, text="Toutes les mesures demandées devront être converties en centimètre, ce dernier \n étant l'unité utilisé pour les réponses.", font=("Courrier", 13), bg="#03EFFA", fg="red") text1.pack() text2.pack() text3.pack() # 加载初始界面 init_interface() frame.pack(expand=YES) def carr(): # 清空当前框架内所有组件 for widget in frame.winfo_children(): widget.destroy() # 添加正方形模块内容 width = 350 height = 299 image = PhotoImage(file="carre.png") canvas = Canvas(frame, width=width, height=height, bd=0, highlightthickness=0, bg="#03EFFA") canvas.create_image(width/2, height/2, image=image, anchor=CENTER) canvas.pack() # 保存图片引用,避免被Tkinter垃圾回收 canvas.image = image def cerc(): # 清空当前框架内所有组件 for widget in frame.winfo_children(): widget.destroy() # 添加圆形模块内容 text1 = Label(frame, text="模块 Cercle : 这里可以添加计算 aire 和 périmètre 的功能", font=("Courrier", 20), bg="#03EFFA", fg="white") text1.pack() def rect(): # 清空当前框架内所有组件 for widget in frame.winfo_children(): widget.destroy() # 添加矩形模块内容 text1 = Label(frame, text="模块 Rectangle : 这里可以添加计算 aire 和 périmètre 的功能", font=("Courrier", 20), bg="#03EFFA", fg="white") text1.pack() def tria(): # 清空当前框架内所有组件 for widget in frame.winfo_children(): widget.destroy() # 添加直角三角形模块内容 text1 = Label(frame, text="模块 Triangle rectangle : 这里可以添加计算 aire 和 périmètre 的功能", font=("Courrier", 20), bg="#03EFFA", fg="white") text1.pack() def quitter(): msg = messagebox.askquestion("Sortir du module","Voulez-vous vraiment quitter ?", icon="error") if msg == "yes": fenetre.destroy() # 创建菜单栏 menu_bar = Menu(fenetre) file_menu = Menu(menu_bar, tearoff=0) file_menu.add_command(label="Carré", command=carr) file_menu.add_command(label="Cercle", command=cerc) file_menu.add_command(label="Rectangle", command=rect) file_menu.add_command(label="Triangle rectangle", command=tria) file_menu.add_command(label="Quitter", command=quitter) menu_bar.add_cascade(label="Séléction", menu=file_menu) fenetre.config(menu=menu_bar) # 启动主循环 fenetre.mainloop()
关键修改点
- 把初始界面内容封装成
init_interface()函数,结构更清晰。 - 每个模块函数里先通过
frame.winfo_children()遍历并销毁框架内的所有组件,再添加新内容。 - 移除了菜单命令里的
frame.pack_forget(),因为现在复用同一个框架,不需要隐藏再重新创建。 - 修复了正方形模块里图片不显示的问题:将
image赋值给canvas.image,保留引用避免被垃圾回收。
内容的提问来源于stack exchange,提问作者Galaktik
相关产品推荐
相关产品推荐

