MagTun
MagTun

Reputation: 6185

Kivy: how to retrieve ids or active states of checkbox (or other widgets) created within python

My app follows 3 steps:

My question is how can I get the state of the checkboxes? When they are "created", each has an id but these ids don't appear when I print self.ids. Also I get an error if I pass any argument to the getcheckboxes_active def. (None is not callable).

The .py:

import kivy
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.label import Label
from kivy.uix.checkbox import CheckBox 
from kivy.uix.button import Button 
from kivy.properties import StringProperty

class MyWidget(BoxLayout):
    input_text = StringProperty("10")


    def show(self, number):
        layout = BoxLayout(padding=10, orientation="vertical")
        for each in range(int(number)):
            layout2 = BoxLayout(padding=10, orientation="horizontal")
            l=Label(bold= True,font_size=20, text='Hello', markup = True)
            c= CheckBox(id = "CheckBox"+str(each))
            layout2.add_widget(l)
            layout2.add_widget(c)
            layout.add_widget(layout2)
        button = Button(text="OK 2")
        button.bind(on_press=self.getcheckboxes_active)  # self.getcheckboxes_active(self, "test") give an error None is not callable
        layout.add_widget(button)
        self.add_widget(layout)

        self.input_text = "Done"

    def getcheckboxes_active(self, *arg):
        '''how to get the active state of all checkboxed created in def show'''
        print(self.ids)  # CheckBoxes id aren't displayed
        print(*arg)
        print("State of all checkboxes")

class MyApp_auto(App):
    def build(self):
        return MyWidget()
MyApp_auto().run()

The .kv: I need to have a .kv because the "step 1 real app" is way more complex than an TextInput and a Button.

<MyWidget>
    orientation: "horizontal"
    TextInput:
        text: root.input_text
        id:input
    Button:
        text:'OK 1'
        on_press: root.show(input.text)

Upvotes: 1

Views: 2736

Answers (2)

JeepersCreepers
JeepersCreepers

Reputation: 9

Possibly a common scenario: From a list of strings, make labels and their corresponding checkbox, using the previously mentioned idea of a dictionary, then show the selected checkbox label as the text of another label.

class BuildRequester(BoxLayout):
    chkref = {}
    def on_checkbox_active(self,chkbox,value):
        self.ids.label2.text = 'Selected ' + self.chkref[chkbox]
    def __init__(self, **kwargs):
        super(BuildRequester,self).__init__(**kwargs)
        prods = [' B_0003',' B_0007',' B_0008', ' B_0200']

        for i in range(4):
            self.add_widget(Label(text=prods[i],italic=True,bold=True))
            chkbox = CheckBox(group='1',color=[0.1,1,0,4])
            chkbox.bind(active=self.on_checkbox_active)
            self.add_widget( chkbox)
            self.chkref[chkbox]= prods[i]

Upvotes: 0

ODiogoSilva
ODiogoSilva

Reputation: 2414

The issue here is that the ids dictionary is only populated with id values that were defined in the .kv file, not in python.

However, you can create you own dictionary that contains the references to the CheckBox widgets. Instead of providing the id property upon the creation of the widget, you could populate a dictionary attribute of MyWidget (let's call it check_ref) that links your id with each CheckBox instance:

class MyWidget(BoxLayout):
    input_text = StringProperty("10")

    check_ref = {}

    def show(self, number):
        layout = BoxLayout(padding=10, orientation="vertical")
        for each in range(int(number)):
            layout2 = BoxLayout(padding=10, orientation="horizontal")
            l=Label(bold= True,font_size=20, text='Hello', markup = True)
            c = CheckBox()

            # Stores a reference to the CheckBox instance 
            self.check_ref["CheckBox"+str(each)] = c

            layout2.add_widget(l)
            layout2.add_widget(c)
            layout.add_widget(layout2)
        button = Button(text="OK 2")
        button.bind(on_press=self.getcheckboxes_active)  # self.getcheckboxes_active(self, "test") give an error None is not callable
        layout.add_widget(button)
        self.add_widget(layout)

        self.input_text = "Done"

    def getcheckboxes_active(self, *arg):
        '''how to get the active state of all checkboxed created in def show'''
        # Iterate over the dictionary storing the CheckBox widgets
        for idx, wgt in self.check_ref.items():
             print(wgt.active)

        # You can also get a specific CheckBox
        # print(self.check_ref[--my id--].active)

Upvotes: 3

Related Questions