Tkinter pack_forget() 和 destroy() 不起作用



我有一个问题,这两个函数不按预期工作。我想使用一个选择表单下拉menù和基于选择两组不同的复选框显示在根窗口。为此,我使用以下代码:

from tkinter import *
import tkinter as tk
def evaluation(form):
form.pack_forget()
form.destroy()
form=Frame(root)
GotPlatform=platform.get()
for elem in PlatformOption[GotPlatform]:
OptionButtonSel[elem]=Checkbutton(form, text=elem)
OptionButtonSel[elem].pack()
form.pack(fill="both", expand = 1)  
PlatformOption={'Option1':["option1-1","option1-2"],'Option2':["option2-1","option2-2"]}
OptionButtonSel={}
root = tk.Tk()
f1=Frame(root)
menuBar = tk.Menu(root)
menu1 = tk.Menu(root)
submenu = tk.Menu(root)
platform = StringVar()
submenu.add_radiobutton(label="Option1", value="Option1", variable=platform,command=lambda:evaluation(f1))
submenu.add_radiobutton(label="Option2", value="Option2", variable=platform,command=lambda:evaluation(f1))
menuBar.add_cascade(label="Options", menu=menu1)
menu1.add_cascade(label="Select option", menu=submenu)
root.config(menu=menuBar)
root.mainloop()

代码工作,但每当我从下拉menù更改选项时,复选框选项被堆叠,而不是像预期的那样被覆盖。

这让我感到困惑,因为我使用了其他代码,它按预期工作:

from tkinter import Tk, Frame, Menu, Label

def show_frame1():
forget_all()
f1.pack(fill="both", expand = 1)  


def show_frame2():
forget_all()
f2.pack(fill="both", expand = 1)  


def forget_all():
f1.pack_forget()
f2.pack_forget()

root = Tk()
f1 = Frame(root)
f2 = Frame(root)
Label(f1, text="MENU SELECTED 1").pack()
Label(f2, text="MENU SELECTED 2").pack()
menubar=Menu(root)
subMenu=Menu(menubar, tearoff = 0)
menubar.add_cascade(label = 'MENU', menu=subMenu)
subMenu.add_command(label = 'SUBMENU1', command = show_frame1)
subMenu.add_command(label = 'SUBMENU2', command = show_frame2)
root.config(menu = menubar)

root.mainloop() 

除了增加了destroy()之外,frame和pack_forget()的用法在我看来是一样的。

我使用Python 3.10.1, IDE Spyder最新版本,Windows 8。

问题的根源在于您创建的表单永远不会出现在屏幕上。您创建了它,但从不调用它的pack。然后在每次单击按钮时将此表单传递给该函数。换句话说,您一直传递原始表单,而不是重新创建的新表单。

最好的解决方案是你的主代码调用pack,place,或grid的形式,然后在函数中你可以删除窗体的子窗体,而不删除窗体本身。

因此,在创建f1后不久添加以下内容:
f1.pack(fill="both", expand=True)

接下来,修改evaluation以销毁子窗体而不是窗体本身:

def evaluation(form):
for child in form.winfo_children():
child.destroy()
GotPlatform=platform.get()
for elem in PlatformOption[GotPlatform]:
OptionButtonSel[elem]=Checkbutton(form, text=elem)
OptionButtonSel[elem].pack()

它给人的感觉是它不能工作,因为小部件对屏幕是不可见的。然而,下面将进一步解释这个主题

pack_forget() not working

为了证明我的理论,我做了一些关于这个话题的其他研究https://www.geeksforgeeks.org/python-forget_pack-and-forget_grid-method-in-tkinter/完美地解释了pack_forget()的概念

最新更新