在Python Tkinter中动态删除小部件

0 投票
1 回答
602 浏览
提问于 2025-04-18 17:40

我在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))

撰写回答