Search code examples
python-3.xkivykivy-languagekivymd

Get the status of a checkbox from a Custom List in Kivy/KivyMD


I'm trying a custom List item based on the KivyMD's documentation examples, but I'm having a problem identifying which of my chechkboxes has been activated. With * args I can access its state and which object it is but it prints like this: {<__ main __. RightCheckbox object at 0x000001B1A62E6970>, False}.

The problem is that "0x000001B1A62E6970" is not a constant value (this value may change with the execution of the code) that represents the checkbox as its id does.

My minimal code KV:

KV = '''
MDCard:
    orientation : 'vertical'
    size_hint : (0.8,0.3)
    pos_hint : {"center_x":.5,"center_y":.5}
    elevation : 15
    padding : 20
    spacing : 30
    id: box
    MDList:
        id: scroll

<ListItemWithCheckbox>:

    IconLeftWidget:
        icon: root.icon

    RightCheckbox: 
'''

And the MainApp and Custom Class definitions:

from kivy.lang import Builder
from kivy.properties import StringProperty
from kivymd.app import MDApp
from kivymd.uix.list import IRightBodyTouch, OneLineAvatarIconListItem
from kivymd.uix.selectioncontrol import MDCheckbox
from kivymd.icon_definitions import md_icons

class ListItemWithCheckbox(OneLineAvatarIconListItem):
    '''Custom list item.'''
    icon = StringProperty("android")

    def on_press(self):
        print(self.text)

class RightCheckbox(IRightBodyTouch, MDCheckbox):
    '''Custom right container.'''

    def on_active(self, *args):
        print(args)

class MainApp(MDApp):
    def build(self):
        return Builder.load_string(KV)

    def on_start(self):
        icons = list(md_icons.keys())
        for i in range(5):
            self.root.ids.scroll.add_widget(
                ListItemWithCheckbox(text=f"Item {i}", icon=icons[i])
            )

MainApp().run()

What I have tried:

I have tried to give a default id for the RightCheckbox to later change it to a unique one when putting the widgets in the list and thus access their states in something like "root.ids.checkboxid" but I don't know how to put it when doing self.root.ids.scroll.add_widget (ListItemWithCheckbox (text = f "Item {i}", icon = icons [i]))

Also in the on_active method (when any checkbox is selected) of the RightCheckbox class I have tried to print various attributes such as MDCheckBox.active .icon .ids. .text but none of them prints anything to help me identify which specific checkbox has been selected

I would really appreciate if anyone can help Thanks


Solution

  • One way to do this is to create a reference to the ListItemWithCheckbox within the RightCheckbox like this:

    <ListItemWithCheckbox>:
    
        IconLeftWidget:
            icon: root.icon
    
        RightCheckbox: 
            listItem: root
    

    Then your on_active() method can use that reference:

    class RightCheckbox(IRightBodyTouch, MDCheckbox):
        '''Custom right container.'''
    
        def on_active(self, rcb, value):
            print(rcb.listItem.text, 'is', value)