使用 python 和 .kv 文件将静态小部件树转换为动态小部件树

converting static widget tree to dynamic using python and .kv file

我正在开发一个应用程序,我想在垂直 BoxLayout 中添加 n 个图像帧。 n 帧的数量取决于桌面屏幕尺寸。接下来,框架将动态填充图像。我能够以固定数量的帧以静态方式开发它。 现在我正在尝试将其转换为动态解决方案,其中将根据屏幕的高度创建 n 个框架小部件(在下面的示例中为 7 个小部件)。我迷路了..... :(

框架应该 'sit' 在顶栏和底栏之间。在 .kv 文件中,这由 # Ilist: 行指示。

我有以下问题:

1) 如何使用 .kv 文件动态添加这些小部件?

2) 我如何引用这些单独的框架小部件来动态分配图像?例如:frame[idx] = swid?

非常感谢您抽出时间提前分享知识。

Python 文件 pplay.py:

from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.properties import StringProperty

class IListItem(Widget):
    sid = StringProperty('')
    image = StringProperty('')
    label = StringProperty('')
    pass

class IList(Widget):
    pass

class pplayHome(BoxLayout):

    def init_player(self):
        global swid

        self.Ilayout = IList()

        for idx in range (1, 7):
            swid = IListItem(
                    sid = "s" + str(idx),
                    image = 'empty_image.png',
                    label = 'Image' + str(idx)
            )
            self.Ilayout.add_widget(swid)

class pplayApp(App):
    def build(self):
        Window.clearcolor = (1,1,1,1)
        Window.borderless = True
        Window.size = 275, 1080
        homeWin = pplayHome()
        homeWin.init_player()
        return homeWin

if __name__ == "__main__":
    pplayApp().run()

和 Kivy 文件 pplay.kv

# File: pplay.kv

<IList@BoxLayout>
    pid: self.pid
    source: self.source
    label: self.label
    size_hint_y: None
    height: "120dp"

    BoxLayout:
        orientation: "vertical"
        Label:
            size_hint: None, 1
            text: root.label

        Image:
            size_hint: None, 1
            source: root.source

<pplayHome>:
    orientation: "vertical"
    ActionBar:
        font_size: 8
        size: (275,25)
        # background color in Kivy acts as a tint and not just a solid color.
        # set a pure white background image first.
        background_image: 'white-bg.png'
        background_color: 0,.19,.34,1
        ActionView:
            ActionPrevious:
                with_previous: False
                app_icon: 'trButton.png'
            ActionOverflow:
            ActionButton:
                icon: 'butt_exit.png'
                on_press: root.exit_player()

#    Ilist:


    BoxLayout:
        height: "10dp"
        size_hint_y: None
        pos_x: 0
        canvas.before:
            Color:
                rgb: 0.55,0.77,0.25     # groen
            Rectangle:
                pos: self.pos
                size: self.size

你们其实很接近。 这是略有改动的 kv 文件,添加了用于说明尺寸的彩色矩形:

# File: pplay.kv

<IListItem@Widget>
    source: ''
    label: ''
    size_hint_y: None
    height: "120dp"
    canvas.before:
        Color:
            rgb: 0.55,0.77*self.idx/7,0.25     # groen
        Rectangle:
            pos: self.pos
            size: self.size
    BoxLayout:
        orientation: "vertical"
        size: root.size
        pos: root.pos

        Label:
            size_hint: None, 1
            text: root.label
            canvas.before:
                Color:
                    rgb: 0.77*root.idx/7,0.55,0.25     # groen
                Rectangle:
                    pos: self.pos
                    size: self.size
        Image:
            size_hint: None, 1
            source: root.source

<pplayHome>:
    orientation: "vertical"
    ActionBar:
        font_size: 8
        size: (275,25)
        # background color in Kivy acts as a tint and not just a solid color.
        # set a pure white background image first.
        background_image: 'white-bg.png'
        background_color: 0,.19,.34,1
        ActionView:
            ActionPrevious:
                with_previous: False
                app_icon: 'trButton.png'
            ActionOverflow:
            ActionButton:
                icon: 'butt_exit.png'
                on_press: root.exit_player()

    IList:
        id: ilist
        orientation: 'vertical'
    BoxLayout:
        height: "10dp"
        size_hint_y: None
        pos_x: 0
        canvas.before:
            Color:
                rgb: 0.55,0.77,0.25     # groen
            Rectangle:
                pos: self.pos
                size: self.size

pplay.py 中,关键部分是使用 self.ids['ilist'] 检索 IList 小部件。它还显示了如何通过区分 属性.

检索其子项(IListItems
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.properties import StringProperty, NumericProperty

class IListItem(Widget):
    idx = NumericProperty(1)
    sid = StringProperty('')
    image = StringProperty('')
    label = StringProperty('')
    pass

class IList(BoxLayout):
    pass

class pplayHome(BoxLayout):

    def init_player(self):
        #global swid

        print self.ids
        ilayout = self.ids['ilist']

        for idx in range (0, 7):
            swid = IListItem(
                    sid = "s" + str(idx),
                    image = 'empty_image.png',
                    label = 'Image' + str(idx),
                    idx=idx
            )
            ilayout.add_widget(swid)
        children_ids = [il.sid for il in ilayout.children]
        print children_ids
        print ilayout.children[children_ids.index('s3')]

class pplayApp(App):
    def build(self):
        # Window.clearcolor = (1,1,1,1)
        Window.borderless = True
        Window.size = 275, 1080
        homeWin = pplayHome()
        homeWin.init_player()
        return homeWin

if __name__ == "__main__":
    pplayApp().run()