Search code examples
pythonfunctionparameter-passingkivykivy-language

(Python Kivy) Indexing Which Button Was Pressed


I am trying to figure out a way to index which button was pressed in a GridLayout so that, for instance, I can put a specific image in that button's background when it is pressed. Here is what I am currently doing, using a function just to try to print the index number as a test before adding more functionality:

    for x in range(15):
        self.buttons.append(Button())
        self.ids.grid_1.add_widget(self.buttons[x])
        self.buttons[x].background_normal = 'YOUTUBE.png'
        self.buttons[x].background_down = 'opacity.png'

        # Make the button switch screens to input from calling the function above
        if edit_mode is True:
            self.buttons[x].bind(on_release=self.SwitchScreenInput)
            self.buttons[x].bind(on_release=self.HoldButtonNum(x))

def HoldButtonNum(x):
    print(x)

Im getting the error:

TypeError: HoldButtonNum() takes 1 positional argument but 2 were given

Process finished with exit code 1


Solution

  • I will make some observations:

    • If HoldButtonNum is an instance method its first parameter must be self.
    • You must use functools.partial or lambda functions to pass arguments to event handler.
    • The function must receive a third parameter which is the instance of the button that launches the event.

    An example:

    from kivy.app import App
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.button import Button
    
    from functools import partial
    class MyGridLayout(GridLayout):
        cols = 5
        def __init__(self):
            super(MyGridLayout, self).__init__()
            self.buttons = []
            for x in range(15):
                self.buttons.append(Button())
                self.add_widget(self.buttons[x])
                self.buttons[x].bind(on_release=partial(self.HoldButtonNum,  x))
    
        def HoldButtonNum(self, x, instance):
            print('Button instance:',  instance)
            print('Button index in list:',  x)
    
    
    class MyKivyApp(App):
        def build(self):
            return MyGridLayout()
    
    def main():
        app = MyKivyApp()
        app.run()
    
    if __name__ == '__main__':
        main()
    

    When a button is pressed the output is like:

    Button index in list: 1    
    Button instance: <kivy.uix.button.Button object at 0x0000018C511FC798>