【问题标题】:Bind children to ListProperty将孩子绑定到 ListProperty
【发布时间】:2021-08-11 17:49:03
【问题描述】:

我的 kivymd 应用中有一个 ListProperty,其中包含特定对象,我想围绕这个列表制作小部件。

为了简单起见,我的应用中有一个 MDBoxLayout,我想使用存储在这个ListProperty

标准方法是遍历列表并根据值创建 MDLabels,这是我当前的代码:

from kivy.lang import Builder
from kivy.properties import ListProperty
from kivymd.uix.label import MDLabel
from kivymd.app import MDApp


class MainApp(MDApp):
    texts = ListProperty(["DEF PATH: ~/Downloads", "PYTHON VERSION: 3.8.10", "PLATFORM: LINUX (KDE NEON)"])

    def __init__(self, **kwargs):
        super(MainApp, self).__init__(**kwargs)
        self.kv = Builder.load_string('''
#:kivy 2.0.0
ScrollView:
    do_scroll_x: False
    do_scroll_y: True
    MDBoxLayout:
        id: box_texts
        orientation: "vertical"
        adaptive_height: True
''')

    def build(self):
        return self.kv

    # my current solution, which I am not happy with
    def on_start(self):
        for txt in self.texts:
            self.kv.ids.box_texts.add_widget(MDLabel(text=txt, size_hint_y=None, height=60))


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

问题是这个 ListProperty 不断变化,并且有多个小部件访问它,因此对于任何更改,我都必须手动更新小部件。

我的问题的假设解决方案是使用 list comprehension 为 MDBoxLayout 的 children 属性分配一个,但由于某种原因它不起作用(可能因为 children 是 AliasProperty):

from kivy.lang import Builder
from kivy.properties import ListProperty
from kivymd.app import MDApp


class MainApp(MDApp):
    texts = ListProperty(["DEF PATH: ~/Downloads", "PYTHON VERSION: 3.8.10", "PLATFORM: LINUX (KDE NEON)"])

    def __init__(self, **kwargs):
        super(MainApp, self).__init__(**kwargs)
        self.kv = Builder.load_string('''
#:kivy 2.0.0
#:import MDLabel kivymd.uix.label.MDLabel
ScrollView:
    do_scroll_x: False
    do_scroll_y: True
    MDBoxLayout:
        id: box_texts
        orientation: "vertical"
        adaptive_height: True
        children: [MDLabel(text=txt) for txt in app.texts]
''')

    def build(self):
        return self.kv


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

有没有像我的第二个解决方案那样真正有效的方法?

【问题讨论】:

    标签: python python-3.x kivy kivy-language kivymd


    【解决方案1】:

    由于textsMainApp 中的Property,因此您可以在MainApp 中定义一个方法,以在texts 更改时构建MDBoxLayout 的子代。这是您的代码的修改版本:

    from kivy.lang import Builder
    from kivy.properties import ListProperty
    from kivymd.app import MDApp
    from kivymd.uix.label import MDLabel
    
    
    class MainApp(MDApp):
        texts = ListProperty()
    
        def __init__(self, **kwargs):
            super(MainApp, self).__init__(**kwargs)
            self.kv = Builder.load_string('''
    #:kivy 2.0.0
    #:import MDLabel kivymd.uix.label.MDLabel
    ScrollView:
        do_scroll_x: False
        do_scroll_y: True
        MDBoxLayout:
            id: box_texts
            orientation: "vertical"
            adaptive_height: True
    ''')
            self.texts = ["DEF PATH: ~/Downloads", "PYTHON VERSION: 3.8.10", "PLATFORM: LINUX (KDE NEON)"]
    
        def on_texts(self, app, new_list):
            box = self.kv.ids.box_texts
            box.clear_widgets()
            for item in new_list:
                box.add_widget(MDLabel(text=item))
    
        def build(self):
            return self.kv
    
    if __name__ == '__main__':
        MainApp().run()
    

    请注意,texts 的初始值直到 kv 加载后才被分配,因此 on_texts() 方法在 kv(及其 ids)加载之前不会被调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-07
      相关资源
      最近更新 更多