是否可以将复杂的布局分类,以便在布局中重复使用?

Can a complex layout be classed so it can be used repeatedly in layout?

我有一个特定的 Boxlayout,其中包含用于连续显示值的标签;现在有几行,每一行都在一个盒子布局中。我想知道我是否可以制作包含所有标签的 boxlayout class。因此,当我转到我的 .kv 文件时,我只需调用 class 而不必重复所有参数。 编辑:我已经放置了相应的 .KV

MDBoxLayout:
    orientation: 'vertical'

    MDToolbar:
        title: "My Stock Tickers"
        
        left_action_items: [["menu", lambda x: x]]
        type: 'top'

    MyBox:
        size_hint: None, None
        size: 400, 100
        
        pos_hint: {"center_x": 0.5}
        #elevation: 20
        padding: 25
        spacing: 25
        
        md_bg_color: [0, .7, 1, 1]

        #Widget:
            #size_hint_y : None
            #height: 10

        MDLabel:
            text: "Enter Ticker"
            font_size: 15
            halign: "center"
            size_hint_y: None
            height: self.texture_size[1]
            

        MDTextFieldRound:
            #id: user
            width: 30
            font_size: 18
            #padding_y: 15
            spacing: '20dp'

        MDFIconButton:
            user_font_size: "15sp"
            icon: "plus"
            opposite_colors: True
            elevation: 8
            md_bg_color: 1, 0, 0, 1
            spacing: '20dp'


        MDLabel:
            id: t_price
            text: "000.00"
            font_size: 15
            halign: "center"
            size_hint_y: None
            height: self.texture_size[1]
            padding_y: 10

        MDLabel:
            id: t_change
            text: "00.00"
            font_size: 15
            halign: "center"
            size_hint_y: None
            height: self.texture_size[1]
            padding_y: 10

    MyBox:
        size_hint: None, None
        size: 400, 200
        md_bg_color: [0, .9, 1, 1]
        #spacing: 10
        orientation: "vertical"
        pos_hint: {"center_x": 0.5}
        


        MyBox:                                   # Title Row
            size_hint: 1, None
            height: 30

            Widget:
                size_hint_x : None
                width: 20
            MDLabel:
                #color: 72/255,89/255,89/255,1
                color: 0,0,0,1
                text: "NAME"
                
                halign: 'left'
                size_hint: None, 1
                width: 100
                

            MDLabel:
                color: (0,0,0,1)
                text: "Value"

            MDLabel:
                color: (0,0,0,1)
                text: "Change"

            MDLabel:
                color: (0,0,0,1)
                text: "Chg %"



        MyRowBox:                                                  #1st Row
            id: row1
            #self.name.text: "Dow"         ????????
            #self.value.text: "000.000"    ????????
            #self.change.text: "000.000"   ????????
            #self.percnt.text: "0.01%"     ????????

我认为可行的示例如下(在 python 中):编辑:我放置了一个工作样本

from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.behaviors import RectangularElevationBehavior
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.label import MDLabel
from kivymd.uix.textfield import MDTextField
from kivymd.uix.button import MDIconButton
from kivymd.uix.widget import MDWidget

class MDFIconButton(MDIconButton):
    pass

class MyBox(MDBoxLayout):
    class update():
        pass

class MyRowBox(MDBoxLayout):
    def __init__(self, **kwargs):
        super(MyRowBox, self).__init__(**kwargs)
        size_hint= 1, None
        height= 30
        self.add_widget(MDWidget(size_hint_x= None, width= 20))
        self.name = (MDLabel( color= [72 / 255, 89 / 255, 89 / 255, 1],halign= 'left', size_hint=[None, 1],width= 100))
        self.add_widget(self.name)
        self.value = MDLabel(halign= 'left')
        self.add_widget(self.value)
        self.change = MDLabel(halign='left')
        self.add_widget(self.change)
        self.percnt = MDLabel(halign='left')
        self.add_widget(self.percnt)

        self.name.text = "Dow"
        self.value.text = "000.000"
        self.change.text = "000.000"
        self.percnt.text = "000.000"
        self.change.font_size = 12
        self.percnt.font_size = 12
        self.name.color = [72 / 255, 89 / 255, 89 / 255, 1]
        self.value.color = [0, 0, 0, 1]
        self.change.color = [0, 0, 0, 1]
        self.percnt.color = [0, 0, 0, 1]
        print(self)

class MyTextField(MDTextField):
    pass

class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "BlueGray"
        return Builder.load_file('MyStocks.kv')


MainApp().run()

因为它是行不通的。这是可以工作的东西还是我太乐观了。我还需要为所有标签设置 ID。

编辑:情况是我不知道如何更新这些值。在 python 文件中,标签有 names,我可以从 python 文件中找到它(正如您从演示中看到的那样)。现在,当 class 在 .kv 文件中实例化时,完整的布局得到 id。问题是如何使用布局的 id 和标签的 names 更改标签的值。请记住布局将被实例化多次。

在此先感谢您提供的任何帮助。谢谢,雷。

如果我正确理解了您的问题,您只需要动态 class。使用 dynamic class,您可以创建一个带有或不带有某些属性的对象,这些属性几乎不需要进一步修改就可以使用。在 kvlang 中,构建和修改 class(之后)更加容易。

首先在 python 中创建一个具有某些确定性(此处为预定或固定数量)属性的动态 class 作为,

class MyRowBox(MDBoxLayout):
    name = StringProperty("NAME")
    value = StringProperty("Value")
    change = StringProperty("Change")
    percnt = StringProperty("Chg %")

然后在kvlang中设计为,

<MyRowBox>:
    md_bg_color: [0.5, .7, 0.2, 1]
    size_hint_y: None
    height: "30dp"

    Widget:
        size_hint_x : None
        width: "20dp"

    MDLabel:
        color: 72/255,89/255,89/255,1
        color: 0,0,0,1
        text: root.name
        halign: 'left'
        size_hint: None, 1
        width: "100dp"

    MDLabel:
        color: (0,0,0,1)
        text: root.value

    MDLabel:
        color: (0,0,0,1)
        text: root.change

    MDLabel:
        color: (0,0,0,1)
        text: root.percnt

因此,您在 .kv 文件中修改后的代码现在应该如下所示,

MDBoxLayout:
    orientation: 'vertical'

    MDToolbar:
        title: "My Stock Tickers"
        left_action_items: [["menu", lambda x: x]]
        type: 'top'

    MDBoxLayout:
        size_hint: None, None
        size: "400dp", "100dp"

        pos_hint: {"center_x": 0.5}
        #elevation: 20
        padding: 25
        spacing: 25

        md_bg_color: [0, .7, 1, 1]

        #Widget:
            #size_hint_y : None
            #height: 10

        MDLabel:
            text: "Enter Ticker"
            font_size: 15
            halign: "center"
            size_hint_y: None
            height: self.texture_size[1]


        MDTextFieldRound:
            #id: user
            width: 30
            font_size: 18
            #padding_y: 15
            spacing: '20dp'

        MDFIconButton:
            user_font_size: "15sp"
            icon: "plus"
            opposite_colors: True
            elevation: 8
            md_bg_color: 1, 0, 0, 1
            spacing: '20dp'


        MDLabel:
            id: t_price
            text: "000.00"
            font_size: 15
            halign: "center"
            size_hint_y: None
            height: self.texture_size[1]
            padding_y: 10

        MDLabel:
            id: t_change
            text: "00.00"
            font_size: 15
            halign: "center"
            size_hint_y: None
            height: self.texture_size[1]
            padding_y: 10

    MyRowBox:    # Same class as a title row
                 # due to its initilization style.
                 # Change it if you need to.
    
    MyRowBox:
        id: row1
        name: "Dow"
        value: "000.000"
        change: "000.000"
        percnt: "0.01%"

    MyRowBox:
        id: row2
        name: "Dow"
        value: "000.000"
        change: "000.000"
        percnt: "0.01%"

    MyRowBox:
        id: row3
        name: "Dow"
        value: "000.000"
        change: "000.000"
        percnt: "0.01%"

    MyRowBox:
        id: row4
        name: "Dow"
        value: "000.000"
        change: "000.000"
        percnt: "0.01%"



<MyRowBox>:
    md_bg_color: [0.5, .7, 0.2, 1]
    size_hint_y: None
    height: "30dp"

    Widget:
        size_hint_x : None
        width: "20dp"

    MDLabel:
        color: 72/255,89/255,89/255,1
        color: 0,0,0,1
        text: root.name
        halign: 'left'
        size_hint: None, 1
        width: "100dp"

    MDLabel:
        color: (0,0,0,1)
        text: root.value

    MDLabel:
        color: (0,0,0,1)
        text: root.change

    MDLabel:
        color: (0,0,0,1)
        text: root.percnt

更新(用例):

class 在 python 中的用法可能是,

# Please add the rest / necessary blocks.

class MainApp(MDApp):
    def build(self):
        self.theme_cls.theme_style = "Dark"
        self.theme_cls.primary_palette = "BlueGray"
        self.root = Builder.load_string(kv)
        return self.root


    def on_start(self):
        box1 = self.root.ids.row1
        box2 = self.root.ids.row2
        # etc.
        for i, box in enumerate([box1, box2, ]):
            box.name = str(i+1)
            box.value = str(100+i)
            box.change = str(i)
            box.percnt = f"{i/100:0.2%}"


MainApp().run()

注:

  1. 我使用 dp 以获得更好的一致性。你可以改变它。
  2. 您可能不再需要 class MyBox