0

I want to iterate through a list of button and bind each button with a different function. But the result is always the last Button's function, not all in the list. Here's my code:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.label import Label
from kivy.uix.stacklayout import StackLayout
from kivy.uix.button import Button

class MyApp(App):
    def build(self):
        parent = StackLayout()
        button_list = []
        for i in range(0,11):
            button_list.append( Button(text = str(i), size_hint = (None,0.15)) )
            print i
        for a_button in button_list:
            parent.add_widget(a_button)
            a_button.bind( on_press = lambda x: parent.add_widget( Label(text = a_button.text) ) )

        return parent 

if __name__ == "__main__":
    MyApp().run()

There is some problem with my lambda function, I guessed.

helvete
  • 2,455
  • 13
  • 33
  • 37
Nguyên DT
  • 145
  • 1
  • 2
  • 7

2 Answers2

0

This is a classic python problem, not actually related to kivy. It is discussed e.g. here.

Community
  • 1
  • 1
inclement
  • 29,124
  • 4
  • 48
  • 60
0

For those still running into this problem 6 years later, here is my solution:

def buttongenerator(layout):

    hellodict = {}

    for k in range(50):
        hellodict[str(k)] = 'Hello' + str(k)
        btn = Button(text=str(k),
                     size_hint_y=None,
                     height='40dp')

        btn.bind(on_release=(lambda instance, var=hellodict[str(k)]: print(var)))
        layout.add_widget(btn)

Layout simply refers to a grid/box layout.

The instance variable is necessary because otherwise the button object will be passed into the lambda function and (in this case) will be printed to the console as a string. The instance variable sort of "absorbs" the button object, if that makes any sense. (The variable does not have to be named instance, it just has to be present)