在Python Tkinter中动态删除小部件
我在Tkinter的框架里有一些小部件,想让用户点击后把它们移除。每个标签旁边都有一个对应的按钮,用来删除这个标签。下面是创建这个框架的代码。
def delFav():
win2 = Tk()
widgets = []
for url in urls:
label = Label(win2, text = url)
button = Button(win2, text = "Delete")
widgets.append({"url" : url, "label" : label, "button" : button})
for w in widgets:
print w["url"], w["label"], w["button"]
w["button"].configure(command = lambda : delete(w["url"], widgets))
w["label"].pack()
w["button"].pack()
删除功能的代码是这样的:
def delete(url, widgets):
for w in widgets:
if w["url"] == url:
print w["label"]
print w["button"]
w["label"].pack_forget()
w["button"].pack_forget()
return
当我想删除一个网址时,我会按下对应的按钮,但总是最后一个按钮被移除。比如说,当我点击第三个按钮时,输出的结果是这样的。
entry/13394 .44877224 .44877384
entry/13277 .44877464 .44877544
entry/8166 .44877624 .44877704
.44877624
.44877704
前面三行显示的是小部件的列表,而点击中间的按钮后,删除功能打印出的结果是最后一个按钮和标签的名字,显示在最后两行。
无论我点击哪个按钮,只有最后一个标签和按钮会消失。该怎么修正这个问题呢?
1 个回答
1
这是一个老问题,叫做“在循环中声明的函数的晚绑定问题”。
w["button"].configure(command = lambda : delete(w["url"], widgets))
在这一行,命令 delete(w["url"], widgets)
假设 w
是循环结束时的最终值,而不是你调用 configure
时的值。因此,点击任何按钮总是会删除最后一个标签。
你可以通过将 w
作为默认参数来强制 lambda “提前绑定”。
w["button"].configure(command = lambda w=w: delete(w["url"], widgets))