【问题标题】:Kivy : how to get widget by id (without kv)Kivy:如何通过 id 获取小部件(没有 kv)
【发布时间】:2023-03-12 11:10:01
【问题描述】:

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

【问题讨论】:

  • 为什么要每次都查找而不是保存参考?如果您在 Python 中自己创建小部件,那么跟踪它们是您的工作。如果您想将名称映射到小部件,请自己使用dict
  • 我明白了,这是一种方法
  • 我有点期待这个 dict 可以由 kivy 自己管理,这意味着由“get widget by id”引起的查找将保持轻松。
  • Kivy 中的 ID 与 HTML/JS 中的 ID 不同。 ID 不是全局唯一的 - 它们对于给定规则是唯一的。这是因为您可能会创建包含 SubWidgetid=subMyWidget。然后,您可能会创建多个 MyWidgets 来复制该 ID。
  • dict 查找速度很快。 Kivy 使用的规则 ID 映射只是dicts。如果您实现自己的dict,查找将与您预期的一样轻松。正如 Nykakin 所建议的那样,在树上行走会起作用,但速度会慢很多。

标签: python widget kivy


【解决方案1】:

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()

【讨论】:

    【解决方案2】:

    您可以直接使用 ID 检索小部件。例如,在您的代码中,您可以使用以下 sn-p 修改 Button 文本:

    self.ids.2.ids.3.ids.1.text = '!!!!'
    

    【讨论】:

      【解决方案3】:

      您可以使用 id 更改每个小部件的属性:

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

      【讨论】:

      • 作为 kivy 的新手,我想进一步了解为什么这个答案被否决。这是因为通常程序应该只在本地知道它需要知道的小部件,还是因为self 在这个例子中更类似于root。有更多细节吗?
      猜你喜欢
      • 2016-06-17
      • 1970-01-01
      • 1970-01-01
      • 2016-06-18
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多