Kivy:如何通过id获取小部件(没有kv)

Mor*_*riB 6 python widget kivy

假设我在 Kivy 中动态定义了一些小部件(按钮)并动态分配它们的 id。在这个用例中我没有使用 kv 语言。我可以保留小部件 id 的引用,而无需跟踪小部件本身:然后我想通过其 id 访问小部件。我可以做类似“通过 id 获取小部件”之类的事情吗?(如果我在 kv 文件中定义了小部件,我可以使用 self.ids.the_widget_id 通过其 id 访问小部件本身)

Nyk*_*kin 3

Kivy 小部件制作树结构。任何小部件的子项都可以通过children属性获得。如果需要,您可以仅保留对根窗口的引用,然后使用walk方法迭代它的小部件:

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

class MyWidget(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        button = Button(text="...", id="1")
        button.bind(on_release=self.print_label)

        l1 = BoxLayout(id="2")
        l2 = BoxLayout(id="3")

        self.add_widget(l1)
        l1.add_widget(l2)             
        l2.add_widget(button)

    def print_label(self, *args):
        for widget in self.walk():
            print("{} -> {}".format(widget, widget.id))

class MyApp(App):
    def build(self):
        return MyWidget()

if __name__ == '__main__':
    MyApp().run()
Run Code Online (Sandbox Code Playgroud)

walk()和方法在 Kivy 1.8.1 版本中walk_reverse()添加。kivy.uix.widget.Widget对于旧版本,您需要自己递归解析树:

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

class MyWidget(BoxLayout):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

        button = Button(text="...", id="1")
        button.bind(on_release=self.print_label)

        l1 = BoxLayout(id="2")
        l2 = BoxLayout(id="3")

        self.add_widget(l1)
        l1.add_widget(l2)             
        l2.add_widget(button)

    def print_label(self, *args):
        children = self.children[:]
        while children:
            child = children.pop()
            print("{} -> {}".format(child, child.id))
            children.extend(child.children)

class MyApp(App):
    def build(self):
        return MyWidget()

if __name__ == '__main__':
    MyApp().run()
Run Code Online (Sandbox Code Playgroud)