Ray
Ray

Reputation: 67

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

I have a specific Boxlayout that contains labels to show values in a row; now there are several rows and each is in a boxlayout. I was wondering if I could make a class of the boxlayout including all the labels. So when I go to my .kv file I just call the class and don't have to repeat all the params. EDIT: IHAVE PLACED THE CORRESPONDING .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%"     ????????

My example of what i thought would work would be something like this (in python): EDIT: I PLACED A WORKING SAMPLE

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

As it is it does not work. is this something that could be made to work or am I being too optimistic. I will also be needing to set Id's for all the labels.

EDIT: The situation is that I do not know how to update the values. In the python file the labels have names which I can address fom the python file (as you can see from the demo). Now, when the class is instantiated in the .kv file the complete layout gets and id. The question is how do I change the values of the labels using the id of the layout and the names of the labels. Bear in mind the layout will be instantiated multiple times.

I thank you in advance for any assistance on this. Thanks, Ray.

Upvotes: 0

Views: 69

Answers (1)

ApuCoder
ApuCoder

Reputation: 2888

If I understood your issues properly, you just need a dynamic class. With dynamic class you can create an object with or without some propertie(s) that can be used with little to no further modifications. In kvlang it is even easier to build and modify the class (afterwards).

First create a dynamic class with some deterministic (here, predetermined or fixed no. of) properties in python as,

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

Then design it in kvlang as,

<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

Thus your modified code in .kv file should now look like,

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

Update (usage case):

The usage case of this class in python could be like,

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

Note:

  1. I used dp for better consistency. You may change it.
  2. You perhaps need the class MyBox no more.

Upvotes: 1

Related Questions