0

I have spend the last few days making an app that I want to implement on a raspberry pi coupled to a 10 inch touchscreen. I am making this app for a student housing association here in Germany.

So the idea is to have the raspberry with the touchscreen installed on/next to/on top of (not sure yet), the common fridge. The fridge only holds drinks in .5L bottles format which cost 0.80€ to 1.10€ each. We don't pay immediately, we just write down our consummations on a list.

What I am trying to do is an app with the kivy library in which I can just click on my name, get a drink and the app would save my consumptions, what I already paid and save these infos in a CSV file. In order to do that I have to generate a number of buttons dynamically (the names of the poeple on the list) with kivy, which I did. But now it seems that I cannot assign them any function when they get pressed. More precisely, the index of each button doesn't seem to have any effect. I don't really know how to explain it so let's look at some code:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout

class grid(App):

    button = [0 for i in range(25)]

    def build(self):
        main = GridLayout(cols = 5)

        for i in range(25):
            self.button[i] = Button(text = str(i))
            self.button[i].bind(on_release =lambda x: grid.printString(str(i)))
            main.add_widget(self.button[i])

        return main

    def printString(string):
        print(string)


app = grid()
app.run()

So this isn't my actual code, it's an example that illustrates the problem. The output I get is 24 for each button I click. What I want is that each button prints it's own index in the button[] list. I have been trying to make this work for hours and I haven't found anything that worked. If anyone knows how to assign these button behaviors correctly, I would be really grateful for your input.

Ismael Padilla
  • 5,246
  • 4
  • 23
  • 35
  • change to `self.button[i].bind(on_release =lambda x, i=i: grid.printString(str(i)))` – eyllanesc Mar 26 '19 at 21:41
  • Thanks a lot, that worked great, if it's not too much, could you tell me why it worked? Or maybe point me to some documentation that explains it? – Sébastien Kovacs Mar 26 '19 at 21:46
  • Have you read the answers to the duplicate question? There they explain it clearly – eyllanesc Mar 26 '19 at 21:48
  • You don't need to use a `lambda`, just use `self.button[i] = Button(text = str(i), on_release=self.button_release)`, and the signature of the `button_release` can be `def button_release(self, button):`. The `button` arg can then be used to get the button text as `button.text`. – John Anderson Mar 26 '19 at 21:50
  • Yes I read them, I didn't understand them at first. Sorry that I asked again. But it's starting to make sense. Thanks a lot for your help. Also thanks John Anderson, I will try your approach as well. – Sébastien Kovacs Mar 26 '19 at 21:56

1 Answers1

0
  • Declare a class CustomButton with inheritance of Button widget
  • Use on_touch_down event and check for collision
  • Assign id when creating CustomButton

Example

main.py

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.gridlayout import GridLayout


class CustomButton(Button):

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            print("Button.id=", self.id)
            return True
        return False


class grid(App):

    def build(self):
        main = GridLayout(cols=5)

        for i in range(25):
            button = CustomButton(id=str(i), text=str(i))
            main.add_widget(button)

        return main


app = grid()
app.run()
Community
  • 1
  • 1
ikolim
  • 15,721
  • 2
  • 19
  • 29