Reputation: 67
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
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
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()
dp
for better consistency. You may change it.MyBox
no more.Upvotes: 1