繁体   English   中英

如何从kivy / python中的小部件树中获取所有小部件的列表。 递归函数无法正常工作

[英]How to get list of all widgets from widget tree in kivy/python. Recursion function not working as expected

我有一个包含多个布局,按钮,复选框,lineedits和其他小部件的应用程序。 我想收集所有这些小部件的列表,以便在应用程序关闭时可以保存它们的状态。 如果可能的话,我宁愿不要将它们存储在一些硬编码列表中,以便以后可以有更多选项来动态修改小部件。

基本问题似乎很简单,我有一个根窗口小部件,然后有子窗口小部件,其中一些拥有自己的子窗口小部件。 小部件树。 我尝试的解决方案是编写一个递归函数以遍历每个小部件并返回子代。

def traverse(item):
    try:
        for i in iter(item):
            for j in traverse(i):
                yield j
    except TypeError:
        yield item

此函数与[1, [2, 3], [4, 5, [[6, 7], 8], 9], 10]的列表一起使用[1, [2, 3], [4, 5, [[6, 7], 8], 9], 10]返回一个包含所有int值的列表。 它甚至可以与我创建并存储在伪造的小部件树中的一些简单类一起使用。 但是,当我将其引入我的应用程序时,我得到的是一个空列表,没有错误或异常。 我对如何使用生成器和yield有基本的想法,但是我必须缺少一些东西。 我已经使用kivy1.9.1和python做了一个基本示例。 如果单击其中一个按钮,则应打印所有子窗口小部件的列表,但不会:

main.py:

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


class MyRootLayout(BoxLayout):

    def traverse(self, item):  # function in question
        try:
            for i in iter(item):
                try:
                    for j in self.traverse(i.children):
                        yield j

                except:
                    yield i

        except TypeError:   
            yield item

    def printwidgetlist(self):  # Called when a button is pressed
        print [child for child in self.traverse(self.children)]


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

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

以及定义窗口小部件树的test.kv文件:

#:kivy 1.9.1

<MyRootLayout>:
    Label:
        id: label_1_id
        text: "label 1"
    Label:
        id: label_2_id
        text: "label 2"
    GridLayout:
        cols: 2
        Button:
            text: "button 1"
            on_press: root.printwidgetlist()
        Button:
            text: "button 2"
            on_press: root.printwidgetlist()
        GridLayout:
            Label:
                id: label_4_id
                text: "other stuff"
    Label:
        id: label_3_id
        text: "label 3"

您可以在每个小部件上调用self.children,这是我用来获取要迭代的孩子列表的功能。 是否有比我尝试的方法更好的获取所有小部件的方法? 我的导线功能是否缺少某些内容? 我敢肯定这很简单。 我不是最高级的程序员。 我想要得到的输出是这样的:

[...
 <kivy.uix.label.Label object at 0x0000000003632BA8>,
 <kivy.uix.gridlayout.GridLayout object at 0x0000000003632AD8>,
 <kivy.uix.label.Label object at 0x0000000003632B40>,
 ...]

首先,将所有输入窗口小部件的名称设置为描述性名称,例如input_widget 您可以直接在kv lang中设置它们。

其次,从根级别递归查找它们:

class MyRootLayout(BoxLayout):

    def save_states(self):

        def save_state(widget):
            for child in widget.children:
                save_state(child)

            if 'input_widget' in child.name:
                # Do something here to save the state.
                pass

        for child in self.children:
            save_state(child)

也许在问这个问题时它不可用,但是现在有Widget.walk方法,它返回一个 Widget.walk 树的生成器,并以向前的布局顺序返回小部件

https://kivy.org/doc/stable/api-kivy.uix.widget.html?highlight=widget%20walk#kivy.uix.widget.Widget.walk

暂无
暂无

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

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