简体   繁体   English

在Kivy中引用动态创建的小部件的ID

[英]Referencing id of dynamically created widget in Kivy

I am having trouble accessing dynamically created children via root.ids.created_in_kv.created_in_py in method bound to button. 我无法通过绑定到button的方法中的root.ids.created_in_kv.created_in_py访问动态创建的子 When I check root.ids.created_in_kv.ids dictionary it is empty, but there are children in root.ids.created_in_kv.children 当我检查root.ids.created_in_kv.ids字典时,它为空,但是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()). 它将接受可能的选择,并动态创建标签-复选框对并将其添加到弹出内容,并且在“应用”按钮上,它将仅返回选择的列表(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中构造带有多个小部件的弹出窗口,但是以下工作方式(建议使其“更精细”,而不是受欢迎):

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 : 我正在创建python-checkbox对(打包在GridLayout中)的python代码,并将其放入选项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? 1)如何使return_selected方法起作用?

2) Is there a way to construct popup more nicely? 2)有没有一种方法可以更好地构造弹出窗口? I can't add widget tree into content ObjectProperty like: 我无法将小部件树添加到内容 ObjectProperty中,例如:

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

It looks like you're a little mixed up on how ids work. 您似乎对ID的工作方式有些困惑。 They are talked about a little bit in the docs: https://kivy.org/docs/api-kivy.lang.html 在文档中对它们进行了一些讨论: https : //kivy.org/docs/api-kivy.lang.html

Basically, they are just special tokens in .kv that lets you reference defined widgets. 基本上,它们只是.kv中的特殊标记,可让您引用已定义的小部件。 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 ) 收集它们并将它们放在定义它们的规则的根窗口小部件ids字典中。这意味着它们不像您引用它们时那样嵌套,它们都在根窗口小部件( SelectorPopupLabeledCheckbox )上

So instead of (from within SelectorPopup ): 因此,而不是(从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. 这也意味着动态添加的小部件将不会出现在ids字典中,但实际上并不需要。 Since you are creating them in code, you can just save references to them yourself (which is harder to do with .kv ). 由于您是用代码创建它们的,因此您可以自己保存对它们的引用(使用.kv很难做到)。

All that being said, it might be a lot easier to use a ListView to display your list of items. 综上所述,使用ListView显示项目列表可能会容易得多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM