Tkinter动态创建菜单:为每个菜单项传递不同参数调用函数
解决Tkinter动态菜单绑定参数的问题
你遇到的问题是lambda的延迟绑定特性导致的:所有动态创建的lambda函数都会引用同一个counter变量,直到你点击菜单项时才会去读取它的值,此时循环已经执行完毕,counter已经是最后一行的行号,所以所有菜单项都会传递这个最终值。
下面是两种直接可行的解决方法:
方案1:给lambda添加默认参数固定值
直接修改循环中的add_command行,通过默认参数把当前counter的值“固定”在lambda内部:
with open(os.path.join(sys.path[0], "AntiTubePlaylists.txt"), "r") as csv_file: csv_reader = csv.reader(csv_file, quotechar='"', delimiter=',') counter = 0 for row in csv_reader: # 给lambda添加默认参数c=counter,保存当前循环的counter值 playlistmenu.add_command(label=row[0], command=(lambda c=counter: ImportPlaylist(c))) counter += 1
原理:每次循环时,Python会把当前counter的数值赋值给lambda的默认参数c,每个lambda都会持有自己独立的c值,而不是共享外部的counter变量。
方案2:使用functools.partial绑定参数
这种方式更直观,适合处理函数参数绑定场景:
- 先导入
functools模块:
import functools
- 修改循环内的代码:
with open(os.path.join(sys.path[0], "AntiTubePlaylists.txt"), "r") as csv_file: csv_reader = csv.reader(csv_file, quotechar='"', delimiter=',') counter = 0 for row in csv_reader: # 用partial把counter的当前值绑定到ImportPlaylist的参数上 playlistmenu.add_command(label=row[0], command=functools.partial(ImportPlaylist, counter)) counter += 1
原理:functools.partial会创建一个新的函数,自动把指定的参数(这里是当前的counter值)传递给目标函数ImportPlaylist,每个菜单项的command都是绑定了对应行号的独立函数。
内容的提问来源于stack exchange,提问作者Willem van Houten
相关产品推荐
相关产品推荐

