Referencing id of dynamically created widget in Kivy

僤鯓⒐⒋嵵緔 提交于 2020-01-03 03:31:30

问题


I am having trouble accessing dynamically created children via root.ids.created_in_kv.created_in_py in method bound to button. When I check root.ids.created_in_kv.ids dictionary it is empty, but there are children in root.ids.created_in_kv.children

What I'm trying to achieve is to create a popup that will act as multiselector. It will accept possible choices and dynamically create label-checkbox pair and add it to popup contents, and on 'Apply' button it will return only chosen list(str()).

I can't constuct popup with multiple widgets in it in kv, but the following works (suggestions to make it 'nicer' more than welcome):

kv code:

<SelectorPopup>:
    title: 'empty'
    BoxLayout:
        id: inside
        orientation: 'vertical'
        BoxLayout:
            id: options
        BoxLayout:
            id: buttons
            orientation: 'vertical'
            Button:
                text: 'Apply'
                on_release: root.return_selected()
            Button:
                text: 'Cancel'
                on_release: root.dismiss()

<LabeledCheckbox@BoxLayout>:
    id: entity
    CheckBox:
        id: choice
    Label:
        text: root.id

And the python code I'm creating the label-checkbox pairs (packaged in GridLayout) and putting it into options BoxLayout:

class SelectorPopup(Popup):
    def return_selected(self):
        selected=[]
        a = self.ids.inside.options.choices.ids # dict is empty
        for item in a.keys():
             selected.append(item) if a[item].ids.choice.value #add if checkbox checked
        return selected

class MultiselectForm(BoxLayout):
    data = ListProperty([])
    def __init__(self, **kwargs):
        super(MultiselectForm, self).__init__(**kwargs)
        self.prompt = SelectorPopup()

    def apply_data(self):
        # write data to self.data
        pass

    def create_popup(self):
        try:
            # some code to check if choices are already created
            check = self.prompt.ids.inside.options.choices.id
        except AttributeError:
            possible = ['choice1','choice2','choice3'] #query db for possible instances
            choices = GridLayout(id='choices',cols=2)
            for entity in possible:
                choice = Factory.LabeledCheckbox(id=entity)
                choices.add_widget(choice)
            self.prompt.ids.options.add_widget(choices)
        self.prompt.open()

Questions:

1) Howto make return_selected method work?

2) Is there a way to construct popup more nicely? I can't add widget tree into content ObjectProperty like:

<MyPopup>:
    content:
        BoxLayout:
            Label:
                text: 'aaa'
            Label:
                text: 'bbb'

回答1:


It looks like you're a little mixed up on how ids work. They are talked about a little bit in the docs: https://kivy.org/docs/api-kivy.lang.html

Basically, they are just special tokens in .kv that lets you reference defined widgets. They are collected and placed in the ids dictionary on the root widget of the rule they are defined in. This means they aren't nested like you are referencing them, they are all on the root widget (SelectorPopup or LabeledCheckbox)

So instead of (from within SelectorPopup):

self.ids.inside.options.choices

You would have:

self.ids.choices

This also means that widgets added dynamically aren't going to be present in the ids dictionary, but they don't really need to be. Since you are creating them in code, you can just save references to them yourself (which is harder to do with .kv).

All that being said, it might be a lot easier to use a ListView to display your list of items.



来源:https://stackoverflow.com/questions/35872322/referencing-id-of-dynamically-created-widget-in-kivy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!