user286508
user286508

Reputation: 29

Kivy Buttons- Sound playing on execute, rather than on click

Me again, here is my code, why is "beep.wav" playing when I launch the application rather than when I press the buttons I assume I have bound it to?

import kivy
import random
from kivy.core.audio import SoundLoader
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout

sound = SoundLoader.load('beep.wav')

red = [1,0,0,1]
green = [0,1,0,1]
blue =  [0,0,1,1]
purple = [1,0,1,1]

class A_Cool_Program(App):
    def Orientation(self, orient):
        self.orient = orient

    def build(self):
        layout = BoxLayout(padding=0, orientation=self.orient)
        colors = [red, green, blue, purple]

        for i in range(5):
            btn = Button(text="Test Button %s" % (i+1), background_color=random.choice(colors))
            layout.add_widget(btn)
            sound = SoundLoader.load('beep.wav')
            btn.bind(on_press=sound.play())
        return layout

if __name__ == "__main__":
    app = A_Cool_Program()
    app.Orientation(orient="vertical")
    app.run()

Upvotes: 0

Views: 766

Answers (1)

inclement
inclement

Reputation: 29460

btn.bind(on_press=sound.play())

This line calls the function, just as you should always expect when you use the function call syntax - you called sound.play(), therefore the function is called and you hear the sound. The bind method doesn't know about any of this, it only sees the return value of the function, which is probably just None.

I think in this case you want instead something like

btn.bind(on_press=lambda *args: sound.play())

This passes in a lambda function, and when that function is called then sound.play() is run. This example is actually unusual because sound.play doesn't seem to accept any arguments, but kivy bindings automatically pass at least the instance of the button, so this code uses a lambda function to eat that argument.

You normally could just do:

def some_function(*args):
    print('the button was pressed!')

...

btn.bind(on_press=some_function)

Note the lack of brackets to actually call some_function. It will be called later when the button is pressed.

Upvotes: 3

Related Questions