访问被拒绝 child id

kivy access child id

我想访问 child 的 ID 来决定是否删除小部件。我有以下代码:

main.py

#!/usr/bin/kivy
# -*- coding: utf-8 -*-

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout


class Terminator(BoxLayout):
    def DelButton(self):
        print("Deleting...")

        for child in self.children:
            print(child)
            print(child.text)

            if not child.id == 'deleto':
                print(child.id)
                #self.remove_widget(child)
            else:
                print('No delete')


class TestApp(App):
    def build(self):
        pass


if __name__ == '__main__':
    TestApp().run()

test.kv

#:kivy 1.9.0

<Terminator>:
    id: masta
    orientation: 'vertical'

    Button:
        id: deleto
        text: "Delete"
        on_release: masta.DelButton()

    Button
    Button

Terminator

但是当使用 print(child.id) 打印 id 时,它总是 returns: None。即使 print(child.text) 正确 returns Delete .

问题

如您在 documentation 中所读:

In a widget tree there is often a need to access/reference other widgets. The Kv Language provides a way to do this using id’s. Think of them as class level variables that can only be used in the Kv language.

从 Python 代码访问 ID 已描述 here。工作示例:

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import ObjectProperty
from kivy.uix.button import Button

Builder.load_string("""
<Terminator>:
    id: masta
    orientation: 'vertical'

    MyButton:
        id: deleto

        button_id: deleto

        text: "Delete"
        on_release: masta.DelButton()

    MyButton
    MyButton
""")

class MyButton(Button):
    button_id = ObjectProperty(None)

class Terminator(BoxLayout):
    def DelButton(self):
        for child in self.children:
            print(child.button_id)       

class TestApp(App):
    def build(self):
        return Terminator()    

if __name__ == '__main__':
    TestApp().run()

要跳过删除带有 "Delete" 标签的按钮,您可以检查其 text 属性。 Hovewer 从循环内部删除会导致错误,因为某些 children 将在您迭代的列表被更改后被跳过:

class Terminator(BoxLayout):
    def DelButton(self):
        for child in self.children:            
            self.remove_widget(child) # this will leave one child

您必须创建 children 个列表才能删除:

class Terminator(BoxLayout):
    def DelButton(self):
        for child in [child for child in self.children]:            
            self.remove_widget(child) # this will delete all children

你的情况:

class Terminator(BoxLayout):
    def DelButton(self):
        for child in [child for child in self.children if child.text != "Delete"]:            
            self.remove_widget(child)

以上是执行任务的不错选择。我在我的代码中非常成功地使用了它们。现在给大家推荐一下Kivy Framework在其文档中直接推荐的可视化代码
看一下,在这个link处清晰可见: https://kivy.org/doc/stable/api-kivy.uix.widget.html?highlight=objectproperty

你很快就能搞定并使用它。 此部分是 - 小部件 class,锚点是 - ids.

这是用您的 kv 语言定义的 ID 字典。仅当您在 kv 语言代码中使用 id 时才会填充此内容。

ids 是一个 DictProperty,默认为空字典 {}。

为每个根级小部件定义填充 ID。例如:

# in kv
<MyWidget@Widget>:
    id: my_widget
    Label:
        id: label_widget
        Widget:
            id: inner_widget
            Label:
                id: inner_label
    TextInput:
        id: text_input
    OtherWidget:
        id: other_widget


<OtherWidget@Widget>
    id: other_widget
    Label:
        id: other_label
        TextInput:
            id: other_textinput





# Then, in python:

>>> widget = MyWidget()
>>> print(widget.ids)
{'other_widget': <weakproxy at 041CFED0 to OtherWidget at 041BEC38>,
'inner_widget': <weakproxy at 04137EA0 to Widget at 04138228>,
'inner_label': <weakproxy at 04143540 to Label at 04138260>,
'label_widget': <weakproxy at 04137B70 to Label at 040F97A0>,
'text_input': <weakproxy at 041BB5D0 to TextInput at 041BEC00>}

>>> print(widget.ids['other_widget'].ids)
{'other_textinput': <weakproxy at 041DBB40 to TextInput at 041BEF48>,
'other_label': <weakproxy at 041DB570 to Label at 041BEEA0>}
>>> print(widget.ids['label_widget'].ids)
{}