Kivy:如何通过ID获取小部件(不使用kv)

6 投票
3 回答
12665 浏览
提问于 2025-04-18 13:32

假设我在Kivy里动态创建了一些小部件(比如按钮),并且给它们分配了一个ID。我在这个情况下没有使用kv语言。我可以只保留小部件的ID,而不需要一直跟踪这个小部件本身:然后我想通过它的ID来访问这个小部件。我能不能做类似“通过ID获取小部件”的操作?(如果我是在kv文件里定义这个小部件,我就可以用self.ids.the_widget_id通过它的ID来访问这个小部件)

3 个回答

0

你可以通过使用ID来改变每个小部件的属性:

self.ids['order_number'].text='S1212'
2

你可以直接通过ID来获取这个小部件。例如,在你的代码中,你可以用下面的代码来修改按钮的文本:

self.ids.2.ids.3.ids.1.text = '!!!!'
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()

walk()walk_reverse()这两个方法是在Kivy的1.8.1版本中加入到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()

撰写回答