Kivy dynamicly created card widget on press function

Viewed 61

I am creating a Kivy app. I am fetching some data like names, email adress and so on from an sql table. depending on how many entrys are found depending on the searched name i want to dynamicly create card widgets. This works fine for now. I want to add a function to click on a widget to edit the data from this entry. But I am unable to assign an id or something to the card widget to check which widget is pressed.

This is part of my function in Main class

        for i, _ in enumerate (records):
            label=MDCard(padding= 4, md_bg_color= self.theme_cls.primary_color, size=( 200, 210), size_hint=(None, None))
            label2=GridLayout(rows=8, cols=2,orientation= "lr-tb")
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][1])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][2])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][3])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][4])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][5])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][6])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][7])))

            label.add_widget(label2)

            self.root.ids.testscreen.add_widget(label)

this code creates my card widgets. I googled for several hours but cant get a solution.

I want something like label.bind (on_press = clicked_card(i))

def clicked_card(i): print(i)

I am very new to python and Kivy and hope someone can help me to find a solution.

2 Answers

You can do essentially what you suggest using the on_touch_down event. For every MDLabel in that loop, do something like this:

        label3 = MDLabel(text=str(records[i][3]))
        label3.bind(on_touch_down=self.clicked_card)
        label2.add_widget(label3)

And add a clicked_card() method like this:

def clicked_card(self, label, touch):
    if label.collide_point(*touch.pos):
        print('clicked label:', label.text)

Since every widget gets the touch event, the collide_point() test is necessary to determine if a label is the one actually touched.

Add to object MDCard

ripple_behavior=True
on_release=lammda x: x

Like this:

label=MDCard(padding= 4, 
             md_bg_color= self.theme_cls.primary_color, 
             size=( 200, 210), 
             size_hint=(None, None),
             ripple_behavior=True
             on_release=lammda x: x)

lammda x: x it`s must be your callback


Edit: answer to "how to identify the clicked Card"

for i, _ in enumerate (records):
            label=MDCard(padding= 4, 
                         md_bg_color= self.theme_cls.primary_color, 
                         size=( 200, 210), 
                         size_hint=(None, None),
                         ripple_behavior=True
                         on_release=lammda x, i=i: self.callback(i)

            label2=GridLayout(rows=8, cols=2,orientation= "lr-tb")
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][1])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][2])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][3])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][4])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][5])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][6])))
            label2.add_widget(MDIcon(icon='cash'))
            label2.add_widget(MDLabel(text=str(records[i][7])))

            label.add_widget(label2)

            self.root.ids.testscreen.add_widget(label)

def callback(self, card):
    print(f"{card}")
Related