Here is my script currently:
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)
There is one class, Soundboard
, and one function, play_sound
, and the script section at the bottom. Sounds is a dict with the pattern {name : sound}
Currently sound
is just a number, and the function play_sound
just prints what is called to it.
The problem I've been having is in the create_button_loop
method of Soundboard
. In the loop, for each name
/sound
combination, a button is created in the dict self.buttons
where name
is the button's text and sound
is passed to play_sound
(the lambda statement).
What I want to happen is for the sound
passed through the lambda statement to be sound
when the button is created, not what sound
is when the button is pressed, so play_sound
should print the original value of sound
. What actually happens is that as sound
gets reassigned later (by the next iteration of the loop), when the button is pressed play_sound
plays whatever the current value of sound
is.
In this example, 3 buttons are created, "a" "b" and "c". When "a" is pressed, "3" is printed (most recent reassignment of sound
is in the last iteration of the for loop, so name
/sound
= c
/3
instead of "1", as it was when button "a" was created.
How can I avoid the sound
value being passed in the lambda statement changing when sound
changes? I'd much prefer some iterated method like this as opposed to writing a different callback function for each {name:sound}
combination, but if that is the best way then let me know. Thank you in advance!