如何为for循环创建的Tkinter按钮设置独立命令以显示对应价格?
解决Tkinter循环创建按钮时命令绑定的变量问题
问题核心是lambda闭包会延迟绑定循环变量,所有按钮的command最终引用的都是循环结束时item的最后值(也就是burgers),所以点击任何按钮都会打印3.50。
修复方法1:给lambda添加默认参数
在lambda里把当前循环的item作为默认参数传入,这样每次循环时都会把当前的item值固定下来,而不是引用后续变化的循环变量:
def print_price(item): print(item_list[item]) item_list = dict(apple=1.20, fish=2.40, chocolate=1.20, butter=2.40, hat=10.00, socks=5.70, eggs=4.00, burgers=3.50) row_index = 0 column_index = 0 for item in item_list: # 给lambda添加默认参数item=item,固定当前循环的item值 tk.Button(item_frame, text=item, height=4, width=6, command=lambda item=item: print_price(item)).grid(row=row_index, column=column_index) column_index += 1 if column_index == 3: row_index += 1 column_index = 0 # 原代码中column_index==6的逻辑无意义(每次到3就重置为0),可按需删除或调整 if column_index == 6: row_index += 1 column_index = 0
修复方法2:使用functools.partial
functools.partial可以预先绑定函数参数,彻底避免闭包的延迟绑定问题:
from functools import partial def print_price(item): print(item_list[item]) item_list = dict(apple=1.20, fish=2.40, chocolate=1.20, butter=2.40, hat=10.00, socks=5.70, eggs=4.00, burgers=3.50) row_index = 0 column_index = 0 for item in item_list: # 用partial把当前item绑定到print_price的参数上 btn_command = partial(print_price, item) tk.Button(item_frame, text=item, height=4, width=6, command=btn_command).grid(row=row_index, column=column_index) column_index += 1 if column_index == 3: row_index += 1 column_index = 0 if column_index == 6: row_index += 1 column_index = 0
另外注意:原代码中column_index == 6的判断逻辑存在问题——因为每次column_index到3就会被重置为0,永远不会达到6,可根据实际布局需求删除或调整该部分逻辑。
内容的提问来源于stack exchange,提问作者dylanobrien
相关产品推荐
相关产品推荐

