Tkinter按钮数组点击后仅最后一个按钮禁用的问题求解
问题原因
你遇到的问题是lambda表达式的闭包延迟绑定导致的:循环里的lambda并没有捕获当前循环的i值,而是引用了循环变量i本身。当循环结束时,i的值已经变成24(因为range(25)的最后一个索引是24),所以不管点击哪个按钮,最终调用set_button_function时传入的参数都是24,只会禁用最后一个按钮。
解决方案
这里提供几种可行的解决办法:
方法1:给lambda添加默认参数绑定当前i值
修改按钮创建的代码,把当前循环的i值作为lambda的默认参数传入,这样每个lambda都会持有自己独立的参数值:
buttons_text_var = [StringVar() for i in range(25)] def set_button_function(button_index): buttons[button_index].config(state="disabled") buttons = [Button(window, textvariable=buttons_text_var[i], # 用idx=i绑定当前循环的i值 command=lambda idx=i: set_button_function(idx), height=button_height, bd=button_border_size, font=(button_text_font, button_text_size), width=button_width) for i in range(25)]
方法2:使用functools.partial绑定参数
用functools.partial可以更清晰地把参数绑定到函数上,避免闭包的问题:
首先导入functools模块:
from functools import partial
然后修改按钮创建代码:
buttons_text_var = [StringVar() for i in range(25)] def set_button_function(button_index): buttons[button_index].config(state="disabled") buttons = [Button(window, textvariable=buttons_text_var[i], command=partial(set_button_function, i), height=button_height, bd=button_border_size, font=(button_text_font, button_text_size), width=button_width) for i in range(25)]
方法3:直接绑定按钮对象(更简洁)
不用通过索引查找按钮,直接把当前创建的按钮对象传给lambda,代码更直观:
buttons_text_var = [StringVar() for i in range(25)] buttons = [] for i in range(25): btn = Button(window, textvariable=buttons_text_var[i], height=button_height, bd=button_border_size, font=(button_text_font, button_text_size), width=button_width) # 绑定当前按钮对象到lambda btn.config(command=lambda b=btn: b.config(state="disabled")) buttons.append(btn)
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

