这是我目前的脚本:
import tkinter as tk
class Soundboard(tk.Frame):
def __init__(self, sounds, master=None):
super().__init__(master)
self.sounds = sounds
self.pack()
self.create_button_loop()
def create_button_loop(self):
self.buttons = {}
for name, sound in self.sounds.items():
self.buttons[name] = tk.Button(self, text=name, command = lambda :play_sound(sound))
self.buttons[name].pack(side='top')
#sound = 10
def play_sound(a_sound):
print(a_sound)
#MAIN SCRIPT
if __name__ == '__main__':
sounds = {'a':1, 'b':2, 'c':3}
board = Soundboard(sounds)
有一个类,Soundboard
,一个函数,play_sound
,以及底部的脚本部分。声音是一个具有模式的字典{name : sound}
当前sound
只是一个数字,函数play_sound
只是打印调用它的内容。
我一直遇到的问题在于Soundboard
create_button_loop
方法。在循环中,对于每个name
/sound
组合,在字典self.buttons
中创建一个按钮,其中name
是按钮的文本,sound
传递给play_sound
(lambda 语句(。
我想发生的是在创建按钮时sound
通过lambda语句传递的sound
,而不是按下按钮时sound
是什么,因此play_sound
应该打印sound
的原始值。实际发生的情况是,当sound
稍后(通过循环的下一次迭代(被重新分配时,当按下按钮时play_sound
播放sound
的当前值。
在此示例中,创建了 3 个按钮,"a"、"b"和"c"。当按下"a"时,打印"3"(最近一次重新分配sound
是在for循环的最后一次迭代中,因此name
/sound
=c
/3
而不是"1",就像创建按钮"a"时一样。
如何避免在 lambda 语句中传递的sound
值在sound
更改时更改?我更喜欢这样的迭代方法,而不是为每个{name:sound}
组合编写不同的回调函数,但如果这是最好的方法,请告诉我。提前谢谢你!
使用functools.partial
而不是 lambda。
from functools import partial
...
self.buttons[name] = tk.Button(self, text=name, command=partial(play_sound, sound))