Tkinter批量创建标签点击时传递对应索引的问题
问题
我编写了以下代码批量创建一组标签,点击标签时会执行label_click_handler函数:
def label_click_handler(i): print("Label " + str(i) + " pressed") # etc. for i in range(10): label = Label(text="Label " + str(i)) label.place(x=i*50, y=0) label.bind("<Button-1>", lambda e:label_click_handler(i))
但遇到的问题是,点击任意标签都会输出:
Label 9 pressed
即无论点击哪个标签,传递给label_click_handler的都是循环最后一个值9。请问如何实现点击对应标签时传递该标签的序号?
原因
lambda表达式绑定的时候不会立即捕获循环变量i的当前值,而是在触发点击事件调用lambda时,才去读取i的当前值。循环结束后i已经变成9,所以所有标签的点击事件都会使用这个值。
解决方法
方法1:给lambda添加默认参数固定当前值
通过给lambda设置默认参数,在每次循环时把当前的i值绑定进去,避免后续调用时读取循环结束后的i:
def label_click_handler(i): print("Label " + str(i) + " pressed") # etc. for i in range(10): label = Label(text="Label " + str(i)) label.place(x=i*50, y=0) label.bind("<Button-1>", lambda e, idx=i: label_click_handler(idx))
方法2:使用functools.partial预先绑定参数
借助functools.partial生成绑定了当前i值的新函数,每个标签绑定独立的处理函数:
from functools import partial def label_click_handler(i): print("Label " + str(i) + " pressed") # etc. for i in range(10): label = Label(text="Label " + str(i)) label.place(x=i*50, y=0) label.bind("<Button-1>", partial(label_click_handler, i))
方法3:给标签对象添加自定义属性存储序号
给每个Label添加自定义属性保存序号,在处理函数中通过事件对象获取该属性:
def label_click_handler(event): print("Label " + str(event.widget.label_idx) + " pressed") # etc. for i in range(10): label = Label(text="Label " + str(i)) label.label_idx = i # 自定义属性存储序号 label.place(x=i*50, y=0) label.bind("<Button-1>", label_click_handler)
内容的提问来源于stack exchange,提问作者YesThisIsMe
相关产品推荐
相关产品推荐

