I have two file test.py and test.kv .
i run test.py then shows show button.
When i click on show button then def abc call.Can someone tell me how to show array in dynamic label and value(Item1=5000.Item2=1000).
Item1 5000
Item2 1000
I am using array
arr = ({'Item1': 5000},{'Item2': 1000})
test.py
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty, NumericProperty
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (600, 600)
class Invoice(Screen):
def __init__(self, **kwargs):
super(Invoice, self).__init__(**kwargs)
def abc(self):
#fetching from database
arr = ({'Item1': 5000},{'Item2': 1000})
print(arr)
class Test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
if __name__ == '__main__':
Test().run()
test.kv
<Button#Button>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
<Label#Label>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
Invoice:
BoxLayout:
orientation: "vertical"
padding : 15, 15
BoxLayout:
orientation: "vertical"
padding : 5, 5
size_hint: .6, None
pos_hint: {'x': .18,}
BoxLayout:
orientation: "horizontal"
padding : 5, 5
spacing: 10, 10
size: 800, 40
size_hint: 1, None
Button:
text: "Show"
size_hint_x: .05
spacing_x: 30
on_press:root.abc()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
size_hint: .5, 1
padding : 0, 15
spacing: 10, 10
size: 500, 30
Button:
text: "Invoice"
text_size: self.size
halign: 'center'
valign: 'middle'
GridLayout:
cols: 2
#orientation: "horizontal"
padding : 5, 0
spacing: 10, 0
#size: 500, 30
size_hint: 1, 1
pos: self.pos
size: self.size
Label:
size_hint_x: .35
text: "Item1"
text_size: self.size
halign: 'left'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Label:
size_hint_x: .15
text: "5000"
text_size: self.size
halign: 'right'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
In your abc() method you can create labels and add them to your layout. In order to do that, I made a few change to your code. I added an id to your GridLayout and changed your custom label class to MyLabel and added it to the py file, so that I could create them in Python. Here is the modified Python file:
from kivy.uix.label import Label
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (600, 600)
class MyLabel(Label):
pass
class Invoice(Screen):
def __init__(self, **kwargs):
super(Invoice, self).__init__(**kwargs)
def abc(self):
#fetching from database
arr = ({'Item1': 5000},{'Item2': 1000})
layout = self.ids['invoices']
for invoice in arr:
for key,val in invoice.items():
lab1 = MyLabel(text=str(key),size_hint_x=.35, halign='left' )
lab2 = MyLabel(text=str(val),size_hint_x=.15, halign='right' )
layout.add_widget(lab1)
layout.add_widget(lab2)
class Test(App):
def build(self):
self.root = Builder.load_file('test.kv')
return self.root
And changes to the kv file included changing Label to MyLabel, moving as much as possible to the MyLabel class, and removing your example labels:
<Button#Button>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
<MyLabel>:
font_size: 15
font_name: 'Verdana'
size_hint_y:None
height: 30
text_size: self.size
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Invoice:
BoxLayout:
orientation: "vertical"
padding : 15, 15
BoxLayout:
orientation: "vertical"
padding : 5, 5
size_hint: .6, None
pos_hint: {'x': .18,}
BoxLayout:
orientation: "horizontal"
padding : 5, 5
spacing: 10, 10
size: 800, 40
size_hint: 1, None
Button:
text: "Show"
size_hint_x: .05
spacing_x: 30
on_press:root.abc()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
size_hint: .5, 1
padding : 0, 15
spacing: 10, 10
size: 500, 30
Button:
text: "Invoice"
text_size: self.size
halign: 'center'
valign: 'middle'
GridLayout:
id: invoices
cols: 2
#orientation: "horizontal"
padding : 5, 0
spacing: 10, 0
#size: 500, 30
size_hint: 1, 1
pos: self.pos
size: self.size
Although the option to iterate over the data and generate the widget dynamically is an option, the truth is that it is unbeatable in the long term. If you have structured information it is appropriate to use a design pattern and kivy offers to use a RecycleView for these cases, this implements the MVC pattern, so we just need to pass the data and establish a view where an appropriate adapter can be provided.
In your case it is enough to design a widget that is what is shown in each row:
<Item#GridLayout>:
cols: 2
text: "" # new property
value: 0 # new property
padding : 5, 0
spacing: 10, 0
Label:
size_hint_x: .35
text: root.text
halign: 'left'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Label:
size_hint_x: .15
text: str(root.value)
halign: 'right'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
And then replace the GridLayout with the RecycleView:
RecycleView:
id: rv
viewclass: 'Item'
RecycleBoxLayout:
default_size: None, dp(30)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
And in the event of the button assign the data, in this case you must convert your data to a list of dictionaries where the fields will be the text and value attribute of Item:
def convert_data(data):
l = []
for item in data:
for key, value in item.items():
l.append({'text': key, 'value': value})
return l
class Invoice(Screen):
def abc(self):
#fetching from database
arr = ({'Item1': 5000},{'Item2': 1000})
# convert to [{'text': 'Item1', 'value': 5000}, {'text': 'Item2', 'value': 1000}]
self.rv.data = convert_data(arr)
Complete Code:
main.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
def convert_data(data):
l = []
for item in data:
for key, value in item.items():
l.append({'text': key, 'value': value})
return l
class Invoice(Screen):
def abc(self):
#fetching from database
arr = ({'Item1': 5000},{'Item2': 1000})
# convert to [{'text': 'Item1', 'value': 5000}, {'text': 'Item2', 'value': 1000}]
self.rv.data = convert_data(arr)
class MyApp(App):
def build(self):
return Builder.load_file('test.kv')
if __name__ == '__main__':
MyApp().run()
test.kv
<Button#Button>:
font_size: 15
size_hint_y:None
height: 30
<Label#Label>:
font_size: 15
size_hint_y:None
height: 30
<Item#GridLayout>:
cols: 2
text: ""
value: 0
padding : 5, 0
spacing: 10, 0
Label:
size_hint_x: .35
text: root.text
halign: 'left'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Label:
size_hint_x: .15
text: str(root.value)
halign: 'right'
valign: 'middle'
canvas.before:
Color:
rgb: .6, .6, .6
Rectangle:
pos: self.pos
size: self.size
Invoice:
rv: rv
BoxLayout:
orientation: "vertical"
padding : 15, 15
BoxLayout:
orientation: "vertical"
padding : 5, 5
size_hint: .6, None
pos_hint: {'x': .18,}
BoxLayout:
orientation: "horizontal"
padding : 5, 5
spacing: 10, 10
size: 800, 40
size_hint: 1, None
Button:
text: "Show"
size_hint_x: .05
spacing_x: 30
on_press:root.abc()
BoxLayout:
orientation: "horizontal"
size_hint: 1, 1
BoxLayout:
orientation: "vertical"
size_hint: .5, 1
padding : 0, 15
spacing: 10, 10
size: 500, 30
Button:
text: "Invoice"
text_size: self.size
halign: 'center'
valign: 'middle'
BoxLayout:
RecycleView:
id: rv
viewclass: 'Item'
RecycleBoxLayout:
default_size: None, dp(30)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
Related
I have managed to get the size of a box layout to change based on the corresponding Label height, however, it doesn't line up perfectly and I cannot figure out why.
I have looked at adding offsets but have had no luck since it ended up making the issue worse
Thank you for any help
MainInterface:
<MainInterface#BoxLayout>:
orientation: "vertical"
Label:
#font_name: "Nunito-Black.ttf"
text: "T R U T H"
size_hint: 1, 0.1
GridLayout:
size_hint: 1, 0.12
cols: 4
Button:
text: "Menu1"
Button:
text: "Menu2"
Button:
text: "Menu3"
Button:
text: "Menu4"
PageLayout:
border: "20dp"
swipe_threshold: 0.2
RecycleView:
viewclass: 'PostGrid'
scroll_y: 1
id: rv
data: app.posts
RecycleBoxLayout:
id: box
default_size: None, None
default_size_hint: 1, None
size_hint_y: None
padding: ["10dp", "16dp"]
spacing: "8dp"
height: self.minimum_height
orientation: 'vertical'
key_size: '_size'
BoxLayout:
orientation: "vertical"
Button:
text: "peni"
Button:
text: "tag # will J"
Button:
text: "Input"
<PostGrid#BoxLayout>:
message_id: -1
orientation: "horizontal"
text: ''
spacing: "10dp"
#size_hint: self.width, None
_size: 0, 74
size: 0, 74
text_size: None, None
BoxLayout:
orientation: "vertical"
spacing: "10dp"
size_hint: .1, 1
size: self.size
Button:
text: "UP"
font_size: "5dp"
size_hint: 1, 0.2
Button:
text: "DOWN"
font_size: "5dp"
size_hint: 1, 0.2
Label:
text: "test"
font_size: "5dp"
size_hint: 1, 0.6
Label:
text: root.text
padding: 5, 5
size_hint: .9, 1
#size: self.texture_size
height: self.texture_size[1]
text_size: self.width, None
color: 0,0,0,1
#text_size: self.width, None
#size_hint: None, 1
#size: self.texture_size
#font_name: "Nunito-Bold.ttf"
#font_size: "12dp"
multiline: True
#size: 1, root.min_height
on_texture_size:
app.update_message_size(
root.message_id,
self.texture_size,
root.width)
pos: self.pos
canvas.before:
Color:
rgba: (0.8, 0.8, 0.8, 1)
RoundedRectangle:
size: self.texture_size
radius: [5, 5, 5, 5]
pos: self.x, self.y
canvas:
Color:
rgba:0,0.9,0.9,1
Line:
width:0.8
rounded_rectangle:(self.x,self.y,self.width,self.height, 5)
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.properties import ListProperty
from kivy.animation import Animation
from kivy.metrics import dp
class TruthApp(App):
posts = ListProperty([{'message_id':0, 'text':"testskjhfjksdhfkjshfjshfjkhskjdfhskjdhfkjshfdkjhsjkdfhskjhdfkjshdfjkhzxczxczxczxcxzczxcxsjkdfhjksdhfkjshkjdfhksjdhfjkshdfjkhsdkjhfkjshdfjkshkjfhskjhfkjshfjkshdkjfhskjhfjshfkjshdfjkshdjkfhskjhfkjshfjksdhjfhsjkdhfjkhsdkjfhskjhfjk\ngdgdgd\ndgdgdg\ndgdgdg\ndggdgd",'_size':[0,0] }, {'message_id':1, 'text':"testskjhfjksdhfkjshfjshfjkhskjdfhskjdhfkjshfdkjhsjkdfhskjhjfhskjhfjk,'_size':[0,0]"}])
def update_message_size(self, message_id, texture_size, max_width):
#print(self.posts)
#print("Here")
self.posts[message_id] = {**self.posts[message_id], '_size':[0, texture_size[1]]}
if __name__ == '__main__':
TruthApp().run()
^ Image showing how the code above runs
The problem is in the viewclass of RecycleView (i.e. PostGrid). You set its heightas such it could not accomodate its children which is supposed to be the minimum height that will place all its children.
Now that's exactly the attr. minimum_height does. With this being applied you also don't need default_size: None, None (especially the height attr.)
With this and other modifications your .kv file should now look like,
MainInterface:
<MainInterface#BoxLayout>:
orientation: "vertical"
Label:
#font_name: "Nunito-Black.ttf"
text: "T R U T H"
size_hint: 1, 0.1
GridLayout:
size_hint: 1, 0.12
cols: 4
Button:
text: "Menu1"
Button:
text: "Menu2"
Button:
text: "Menu3"
Button:
text: "Menu4"
PageLayout:
border: "20dp"
swipe_threshold: 0.2
RecycleView:
viewclass: 'PostGrid'
scroll_y: 1
id: rv
data: app.posts
RecycleBoxLayout:
id: box
default_size_hint: 1, None
size_hint_y: None
padding: ["10dp", "16dp"]
spacing: "8dp"
height: self.minimum_height
orientation: 'vertical'
key_size: '_size'
BoxLayout:
orientation: "vertical"
Button:
text: "peni"
Button:
text: "tag # will J"
Button:
text: "Input"
<PostGrid#BoxLayout>:
message_id: -1
orientation: "horizontal"
text: ''
spacing: "10dp"
size_hint_y: None
#_size: 0, 74
height: self.minimum_height
text_size: None, None
BoxLayout:
orientation: "vertical"
spacing: "10dp"
size_hint: .1, 1
Button:
text: "UP"
font_size: "5dp"
size_hint: 1, 0.2
Button:
text: "DOWN"
font_size: "5dp"
size_hint: 1, 0.2
Label:
text: "test"
font_size: "5dp"
size_hint: 1, 0.6
Label:
text: root.text
padding: 5, 5
#size_hint: .9, 1
#size: self.texture_size
size_hint_y: None
height: self.texture_size[1]
text_size: self.width, None
color: 0,0,0,1
#text_size: self.width, None
#size_hint: None, 1
#size: self.texture_size
#font_name: "Nunito-Bold.ttf"
#font_size: "12dp"
multiline: True
#size: 1, root.min_height
on_texture_size:
app.update_message_size(
root.message_id,
self.texture_size,
root.width)
pos: self.pos
canvas.before:
Color:
rgba: (0.8, 0.8, 0.8, 1)
RoundedRectangle:
size: self.texture_size
radius: [5, 5, 5, 5]
pos: self.x, self.y
canvas:
Color:
rgba:0,0.9,0.9,1
Line:
width:0.8
rounded_rectangle:(self.x,self.y,self.width,self.height, 5)
I'm trying to change the background color of the Recycleview table based on the data value of the cells. So, I'would like to change the color only the in the cells containing a specific string of text.
The Goal is to change the color when text is = '1'
Somebody could help?
Here is my code, a simple working app.
.py file:
from kivy.core.window import Window
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleview.views import RecycleDataViewBehavior
from kivy.uix.label import Label
from kivy.properties import BooleanProperty
from kivy.uix.recyclegridlayout import RecycleGridLayout
from kivy.uix.behaviors import FocusBehavior
from kivy.uix.recycleview.layout import LayoutSelectionBehavior
class ScreenManagement(ScreenManager):
pass
class Sfondo_tabella(RecycleDataViewBehavior, Label):
index = None
selected = BooleanProperty(False)
selectable = BooleanProperty(False)
class RecycleGridLayout(FocusBehavior, LayoutSelectionBehavior, RecycleGridLayout):
pass
class Schermo_1(Screen):
data_list = ['1', '2', '3', '2', '1', '3', '3', '2', '1']
class Temp_kvApp(App):
Window.size = (1182, 739)
if __name__ == "__main__":
Temp_kvApp().run()
.kv file:
ScreenManager:
id: screen_manager
name: "screen_manager"
Schermo_1:
id: schermo_1
name: "Schermo_1"
manager: screen_manager
<Sfondo_tabella>:
color: 0,0,0,1
font_size: self.height * 0.5
text_size: self.width, None
valign: 'top'
halign: 'center'
canvas.before:
Color:
rgba: (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
canvas:
Color:
rgba:0,0,0,1
Line:
width:0.5
rectangle:(self.x,self.y,self.width,self.height)
<Schermo_1>
BoxLayout:
orientation: "vertical"
GridLayout:
size_hint: 1, 0.1
height: 50
cols: 1
Label:
font_size: self.height / 1.75
text_size: self.width, None
valign: 'top'
halign: 'left'
color: 1, 1, 1 ,1
text: ""
canvas.before:
Color:
rgb: 0.803, 0.486, 0.176
Rectangle:
pos: self.pos
size: self.size
GridLayout:
id: tasti
size_hint: 1, 0.075
cols: 3
#COL_1
Button:
id: col_1
text: "COL_1"
size_hint_x: 0.33
font_size: self.height / 2.5
text_size: self.width, None
valign: 'top'
halign: 'center'
background_color: 1.22, 1.22, 1.22, 1
#COL_2
Button:
id: col_2
text: "COL_2"
size_hint_x: 0.33
font_size: self.height / 2.5
text_size: self.width, None
valign: 'top'
halign: 'center'
background_color: 1.22, 1.22, 1.22, 1
#COL_3
Button:
id: col_3
text: "COL_3"
size_hint_x: 0.33
font_size: self.height / 2.5
text_size: self.width, None
valign: 'top'
halign: 'center'
background_color: 1.22, 1.22, 1.22, 1
BoxLayout:
RecycleView:
id: tabella_lista_costi_aggiuntivi
viewclass: 'Sfondo_tabella'
data: [{'text': str(x)} for x in root.data_list]
scroll_y: 1
effect_cls: "ScrollEffect" # prevents overscrolling
RecycleGridLayout:
cols: 3
cols_minimum: {0: col_1.width, 1: col_2.width, 2: col_3.width}
size_hint: 1, None
default_size: None, dp(col_1.height/1.75)
default_size_hint: 1, None
height: self.minimum_height
width: self.minimum_width
This can be done in the canvas.before instruction under <Sfondo_tabella> section like below:
<Sfondo_tabella>:
color: 0,0,0,1
font_size: self.height * 0.5
text_size: self.width, None
valign: 'top'
halign: 'center'
canvas.before:
Color:
rgba: (0, 1, 0, 1) if root.text == '1' else (1, 1, 1, 1)
Rectangle:
pos: self.pos
size: self.size
canvas:
Color:
rgba:0,0,0,1
Line:
width:0.5
rectangle:(self.x,self.y,self.width,self.height)
Here the background of the cell would be green if the cell text is '1' otherwise it would be white.
good day
is it possible to have multiple instances of a screen each using unique data? for example, i have a 'homescreen' with various buttons for various categories that takes you to a batch list screen unique to that category where you can add batches to be listed. each buttons batch list screen would have unique data to that category but the template for all batch list screens are the same.
ive made a simple example for one category but in order to expand it to the others would i need to repeat the code and create appropriately named .kv files and add each screen to the screen manager.
.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen
from kivy.uix.behaviors.touchripple import TouchRippleButtonBehavior
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.uix.textinput import TextInput
class CapitalInput(TextInput):
def insert_text(self, substring, from_undo=False):
s = substring.upper()
return super(CapitalInput, self).insert_text(s, from_undo=from_undo)
class RippleButton(TouchRippleButtonBehavior, Button):
def on_touch_down(self, touch):
collide_point = self.collide_point(touch.x, touch.y)
if collide_point:
touch.grab(self)
self.transparency = self.background_color[3]
self.background_color[3] = 0.5 # set transparency to half (0.5)
self.ripple_show(touch)
self.dispatch('on_press')
return True
return False
def on_touch_up(self, touch):
if touch.grab_current is self:
touch.ungrab(self)
self.ripple_fade()
def defer_release(dt):
self.background_color[3] = self.transparency
self.dispatch('on_release')
Clock.schedule_once(defer_release, self.ripple_duration_out)
return True
return False
class AddBatchScreen(Screen):
pass
class BatchScreen(Screen):
pass
class HomeScreen(Screen):
pass
gui = Builder.load_file('BatchTracker.kv')
class BatchTrackerApp(App):
def build(self):
return gui
def insert(self, value):
bs = self.root.get_screen('batch_screen')
bs.ids.rv.data.insert(0, {'value': value or 'default value'})
if __name__ == '__main__':
BatchTrackerApp().run()
BatchTraker.kv
#:kivy 1.11.1
#:include batchscreen.kv
#:include add_batch_screen.kv
#:include homescreen.kv
#:import hex kivy.utils.get_color_from_hex
#:import TouchRippleButtonBehavior kivy.uix.behaviors.touchripple
#:import SlideTransition kivy.uix.screenmanager.SlideTransition
ScreenManager:
id: screen_manager
HomeScreen:
name: 'home_screen'
id: home_screen
BatchScreen:
name: 'batch_screen'
id: batch_screen
AddBatchScreen:
name: 'add_batch_screen'
id: add_batch_screen
<RoundButton#RippleButton>:
background_color: (0,0,0,0)
background_normal: ''
back_color: (1,0,1,1)
border_radius: [20]
canvas.before:
Color:
rgba: self.back_color
RoundedRectangle:
size: self.size
pos: self.pos
radius: self.border_radius
homescreen.kv
<HomeScreen>:
BoxLayout:
orientation: 'vertical'
canvas:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
Label:
canvas.before:
Color:
rgba: 1, 0.7, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
size_hint_y: None
pos_hint: {'top': .1}
text: 'Home Screen'
font_size: 40
GridLayout:
rows: 4
AnchorLayout:
canvas:
Color:
rgba: 0.1, 0.1, 1, 0.9
Rectangle:
pos: self.pos
size: self.size
Button:
pos_hint: {'center_x': 0.5}
size_hint: 0.5, 0.7
halign: 'center'
valign: 'middle'
text: 'Isolations'
font_size: 40
size: self.texture_size
text_size: self.width, None
on_press: print('isolations')
on_release: root.manager.current = 'batch_screen'
AnchorLayout:
canvas:
Color:
rgba: 0.1, 0.1, 1, 0.9
Rectangle:
pos: self.pos
size: self.size
Button:
pos_hint: {'center_x': 0.5}
size_hint: 0.5, 0.7
halign: 'center'
valign: 'middle'
text: 'QPCR'
font_size: 40
size: self.texture_size
text_size: self.width, None
on_release: root.manager.current = 'batch_screen'
AnchorLayout:
canvas:
Color:
rgba: 0.1, 0.1, 1, 0.9
Rectangle:
pos: self.pos
size: self.size
Button:
pos_hint: {'center_x': 0.5}
size_hint: 0.5, 0.7
halign: 'center'
valign: 'middle'
text: 'PCR'
font_size: 40
size: self.texture_size
text_size: self.width, None
AnchorLayout:
canvas:
Color:
rgba: 0.1, 0.1, 1, 0.9
Rectangle:
pos: self.pos
size: self.size
Button:
pos_hint: {'center_x': 0.5}
size_hint: 0.5, 0.7
halign: 'center'
valign: 'middle'
text: 'Electrophoresis'
font_size: 40
size: self.texture_size
text_size: self.width, None
batchscreen.kv
<Row#BoxLayout>:
canvas.before:
Color:
rgba: 0.5, 0.5, 0.5, 1
Rectangle:
size: self.size
pos: self.pos
value: ''
Button:
text: root.value
font_size: sp(80)
on_press: print(f'pressed button {root.value}')
<BatchScreen>:
rv: rv #to expose the widget
FloatLayout:
canvas:
Color:
rgba: hex('c6e2ff')
Rectangle:
pos: self.pos
size: self.size
FloatLayout:
canvas.before:
Color:
rgba: hex('b3b3ff')
RoundedRectangle:
radius: 0,0,25,25
pos: self.pos
size: self.size
pos_hint: {'top':1}
size_hint: 1, .1
Label:
id: lb
text: 'User'
font_size: 60
pos_hint: {'top': 1, 'x': .15}
size_hint: .2, .8
RoundButton:
text: 'Sign Out'
font_size: 40
on_release: print('Sign Out pressed')
pos_hint: {'top': .95, 'x': .55}
size_hint: .4, .8
BoxLayout:
canvas.before:
Color:
rgba: hex('eaec3c')
Rectangle:
pos: self.pos
size: self.size
pos_hint: {'center_x':.5,'center_y':.5}
size_hint: 0.9,0.8
RecycleView:
id: rv
viewclass: 'Row'
scroll_type: ['bars', 'content']
scroll_wheel_distance: dp(114)
bar_width: dp(10)
RecycleBoxLayout:
default_size: None,100
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
GridLayout:
cols:3
canvas.before:
Color:
rgba: hex('969c9c')
Rectangle:
pos: self.pos
size: self.size
pos_hint: {'y': 0}
size_hint: 1, .1
RoundButton:
id: add_batch
text: 'Add Batch'
font_size: 30
on_press: root.manager.transition = SlideTransition(direction="left")
on_release: root.manager.current = 'add_batch_screen'
pos_hint: {'center_y': .5, 'x': .05}
size_hint: .4, .8
back_color: hex('62fd00')
RoundButton:
text: 'Remove Batch'
font_size: 30
halign: 'center'
valign: 'middle'
size: self.texture_size
text_size: self.width, None
on_release: print('Remove pressed')
on_release: print(root.manager.ids.batch_screen.rv.data)
pos_hint: {'center_y': .5, 'x': .55}
size_hint: .4, .8
back_color: hex('fd0000')
RoundButton:
text: 'Back'
font_size: 30
halign: 'center'
valign: 'middle'
size: self.texture_size
text_size: self.width, None
on_press: print('Back pressed')
on_release: root.manager.current = 'home_screen'
pos_hint: {'center_y': .5, 'x': .55}
size_hint: .4, .8
back_color: hex('0000ff')
add_batch_screen.kv
<AddBatchScreen>:
canvas:
Color:
rgba: 0,0,1,1
Rectangle:
pos: self.pos
size: self.size
CapitalInput:
id: capital_input
size_hint: .9, .15
pos_hint: {'center_x': .5, 'y': .6}
font_size: 40
padding: [0, (self.height-self.line_height)/2]
hint_text: 'Batch No.'
multiline: False
halign: 'center'
Button:
id: addbtn
text: 'Add'
size_hint: .4, .08
pos_hint: {'center_x': .5, 'y': .2}
on_press: app.insert(capital_input.text) if capital_input.text != '' else None
on_release: capital_input.text = ''
Button:
text: 'Batch List'
size_hint: .4, .08
pos_hint: {'center_x': .5, 'y': .1}
on_press: root.manager.transition = SlideTransition(direction="right")
on_release: root.manager.current = 'batch_screen'
on_release: print(root.manager.ids.batch_screen.rv.data)
As this is a lot of code you will have a hard time finding someone to give you a specific answer. Without looking through all of your code, yes it is possible to have multiple instances of a screen with unique data. This is exactly the use case of class instances. You simply need to pass a variable, list or object into the instance. I will give you a short example, then you should be able to figure it out yourself for your code.
class MyReusableScreen(Screen):
def __init__(self, data, **kwargs):
super(MyReusableScreen, self).__init__(**kwargs)
self.data = data
mylabel = Label(text=self.data['mylabel_text'])
We added the attribute data to the class. Now we have to pass the data when we initialize the class instance
data1 = {'mylabel_text': 'first label'}
data2 = {'mylabel_text': 'second label'}
screen1 = MyReusableScreen(data=data1)
screen2 = MyReusableScreen(data=data2)
Like this we added unique label texts to the class instances labels. I guess you should now be able to build it up on your own. In case you defined a label in kv language, give it an id like for exanple id: mylabel and then assign the data value like this within you screen mylabel.text = self.data['mylabel_text']. I hope this helps you and if you struggle with something just give me a sign.
I'm having issues with refreshing a BoxLayout of widgets by removing them and then rebuilding the widgets based on the list 'Groups'. When on the EditDeviceGroups screen, the 'create' button should add an element to the list and forward the user to the GroupTemplateScreen, which it does.
The issue occurs when the user uses the back button to return to the EditDeviceGroups screen. At that point, I thought the on_enter method would refresh the widgets to include the new element, but the list shows no changes.
I assume it's some sort of issue with classes and instances, but I cant quite see around this one as this is my first real attempt with Kivy.
soundclout.py
from kivy.app import App
from kivy.properties import ObjectProperty, ListProperty, StringProperty
from kivy.uix.listview import ListItemButton
from kivy.uix.screenmanager import ScreenManager, Screen, WipeTransition
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button,Label
from kivy.graphics import Color,Rectangle,InstructionGroup
class GroupTemplateScreen(Screen):
def remove(self):
pass
class HomeScreen(Screen):
skipBuild = 'build_timeline_screen_6'
#skips build option if already timeline is already built
def skip_build_screen(self,value):
if value is 1:
print('HomeScreen.skip_build_screen')
self.skipBuild = 'edit_timeline_screen_7'
class EditDeviceGroupsScreen(Screen):
#Groups = [GroupNo,null]
Groups = [[1,10],[2,20]]
def on_enter(self):
self.ids.glayout2.clear_widgets()
for i in xrange(0,len(EditDeviceGroupsScreen().Groups)):
##THISPRINT##
print(str(EditDeviceGroupsScreen().Groups[i][0]))
addedGroup = BoxLayout(size_hint_y=None,height='120sp',orientation='horizontal')
addedButton=Button(text="Group " + str(EditDeviceGroupsScreen().Groups[i][0]) + " Settings",font_size=25)
addedGroup.add_widget(addedButton)
self.ids.glayout2.add_widget(addedGroup)
#Removes all widget on leaving to prevent the creation of duplicate widgets
def nav_to_group(self):
self.manager.current = 'edit_group_behaviour_screen_9'
def create_group(self):
base = 1
for i in xrange(0,len(EditDeviceGroupsScreen().Groups)):
if base < EditDeviceGroupsScreen().Groups[i][0]:
base = EditDeviceGroupsScreen().Groups[i][0]
EditDeviceGroupsScreen().Groups.append([base+1,(base+1)*10])
#manages screens
class Manager(ScreenManager):
home_screen = ObjectProperty()
edit_device_groups_screen = ObjectProperty()
group_template_screen= ObjectProperty()
def update(self):
self.connected_device_list._trigger_reset_populate()
self.current_screen.update()
class SoundCloutApp(App):
def build(self):
return Manager(transition=WipeTransition())
if __name__=='__main__':
SoundCloutApp().run()
soundclout.kv
#: kivy 1.10.0
#: import hex kivy.utils.get_color_from_hex
#: import main soundclout
#: import ListAdapter kivy.adapters.listadapter.ListAdapter
#: import ListItemButton kivy.uix.listview.ListItemButton
#: import ScrollView kivy.uix.scrollview
<GroupTemplateScreen>:
rows: 2
spacing: 10
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size_hint_y: None
height: 50
spacing: 10
pos: root.x, (root.height-50)
# Make the background for the toolbar blue
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
on_press: root.manager.current = 'homescreen_1'
background_normal: 'icons/home.png'
size_hint_x: None
width:50
BoxLayout:
size_hint_y: None
height: 500
spacing: 50
padding: 20
pos: root.x, (root.height-560)
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size_hint_y: None
orientation: "horizontal"
height: 50
spacing: 10
padding: 0
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
size_hint_x: None
size_hint_y: None
height: 50
width:100
text: 'Back'
on_release: root.manager.current = 'edit_device_groups_screen_5'
Button:
size_hint_x: None
size_hint_y: None
height: 50
width:100
text: 'Remove'
#have to change first argument, for now assume switch is on
on_press: root.remove()
on_release:root.manager.current = 'edit_device_groups_screen_5'
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#ffffff')
Rectangle:
pos: self.pos
size: self.size
#Devices connected
BoxLayout:
orientation: "horizontal"
canvas:
Color:
rgba: hex('#98a6b3')
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'Name:'
font_size: 24
#TODO
Label:
text: 'Group 1'
font_size: 24
#Devices connected
BoxLayout:
orientation: "horizontal"
canvas:
Color:
rgba: hex('#98a6b3')
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'Devices:'
font_size: 24
#TODO
Label:
text: '1,2,3,4'
font_size: 24
<HomeScreen>:
rows: 2
spacing: 10
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size_hint_y: None
height: 50
spacing: 10
pos: root.x, (root.height-50)
# Make the background for the toolbar blue
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
on_press: root.manager.current = 'homescreen_1'
background_normal: 'icons/home.png'
size_hint_x: None
width:50
BoxLayout:
size_hint_y: None
height: 500
spacing: 50
padding: 50
pos: root.x, (root.height-560)
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
text: "Start"
font_size: 20
Button:
text: "Device Tester"
font_size: 20
Button:
text: "Connect Devices"
font_size: 20
Button:
text: "Edit Device Groups"
font_size: 20
on_press: root.manager.current = 'edit_device_groups_screen_5'
Button:
text: "Edit Group Behavior"
font_size: 20
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Label:
text: "Connected Devices"
font_size: 30
<EditDeviceGroupsScreen>:
rows: 2
spacing: 10
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
#ToolBar
BoxLayout:
size_hint_y: None
height: 50
spacing: 10
pos: root.x, (root.height-50)
# Make the background for the toolbar blue
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
on_press: root.manager.current = 'homescreen_1'
background_normal: 'icons/home.png'
size_hint_x: None
width:50
BoxLayout:
size_hint_y: None
height: 500
spacing: 50
padding: 20
pos: root.x, (root.height-560)
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
size_hint_x: None
size_hint_y: None
height: 50
size: self.size
text: 'create group'
on_press: main.EditDeviceGroupsScreen().create_group()
on_release: root.manager.current = 'group_template_screen_11'
#Groups holder
BoxLayout:
orientation: "vertical"
spacing: 5
padding: 5
canvas:
Color:
rgba: hex('#ffffff')
Rectangle:
pos: self.pos
size: self.size
#Adds Scrollability
ScrollView:
do_scroll_x:False
do_scroll_Y:True
BoxLayout:
id: glayout2
orientation: 'vertical'
spacing: 5
size_hint_y: None
height: self.minimum_height
<Manager>:
id: screen_manager
home_screen: home_screen
edit_device_groups_screen: edit_device_groups_screen
group_template_screen: group_template_screen
HomeScreen:
id: home_screen
name: 'homescreen_1'
manager: screen_manager
EditDeviceGroupsScreen:
id: edit_device_groups_screen
name: 'edit_device_groups_screen_5'
manager: screen_manager
GroupTemplateScreen:
id: group_template_screen
name: 'group_template_screen_11'
manager: screen_manager
#Problem#
The EditDeviceGroups screen is not refreshed with the newly added widgets because when the Back button is pressed, another instance of EditDeviceGroupScreen was instantiated.
#Solution#
With the following changes, when the user clicked the back button to return to the EditDeviceGroups screen, the on_enter method refreshed the widgets to include the new element added. Please refer to the example and output for details.
##soundclout.kv##
Deleted #:import main soundclout
Replaced main.EditDeviceGroupsScreen().create_group() with root.create_group()
##soundclout.py##
Replace all occurrence of EditDeviceGroupsScreen(). with self.
#Example#
##main.py##
from kivy.app import App
from kivy.properties import ObjectProperty, ListProperty, StringProperty
from kivy.uix.listview import ListItemButton
from kivy.uix.screenmanager import ScreenManager, Screen, WipeTransition
from kivy.uix.gridlayout import GridLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.scrollview import ScrollView
from kivy.uix.button import Button, Label
from kivy.graphics import Color, Rectangle, InstructionGroup
class GroupTemplateScreen(Screen):
def remove(self):
pass
class HomeScreen(Screen):
skipBuild = 'build_timeline_screen_6'
# skips build option if already timeline is already built
def skip_build_screen(self, value):
if value is 1:
print('HomeScreen.skip_build_screen')
self.skipBuild = 'edit_timeline_screen_7'
class EditDeviceGroupsScreen(Screen):
# Groups = [GroupNo, null]
Groups = [[1, 10], [2, 20]]
def on_enter(self):
print("EditDeviceGroupsScreen.on_enter:")
self.ids.glayout2.clear_widgets()
for i in range(0, len(self.Groups)):
##THISPRINT##
print(str(self.Groups[i][0]))
addedGroup = BoxLayout(size_hint_y=None, height='120sp', orientation='horizontal')
addedButton = Button(text="Group " + str(self.Groups[i][0]) + " Settings", font_size=25)
addedGroup.add_widget(addedButton)
self.ids.glayout2.add_widget(addedGroup)
# Removes all widget on leaving to prevent the creation of duplicate widgets
def nav_to_group(self):
self.manager.current = 'edit_group_behaviour_screen_9'
def create_group(self):
base = 1
for i in range(0, len(self.Groups)):
if base < self.Groups[i][0]:
base = self.Groups[i][0]
self.Groups.append([base+1, (base+1)*10])
# manages screens
class Manager(ScreenManager):
home_screen = ObjectProperty()
edit_device_groups_screen = ObjectProperty()
group_template_screen= ObjectProperty()
def update(self):
self.connected_device_list._trigger_reset_populate()
self.current_screen.update()
class SoundCloutApp(App):
def build(self):
return Manager(transition=WipeTransition())
if __name__ == '__main__':
SoundCloutApp().run()
##soundclout.kv##
#:kivy 1.10.0
#:import hex kivy.utils.get_color_from_hex
#:import ListAdapter kivy.adapters.listadapter.ListAdapter
#:import ListItemButton kivy.uix.listview.ListItemButton
#:import ScrollView kivy.uix.scrollview
<GroupTemplateScreen>:
rows: 2
spacing: 10
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size_hint_y: None
height: 50
spacing: 10
pos: root.x, (root.height-50)
# Make the background for the toolbar blue
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
on_press: root.manager.current = 'homescreen_1'
background_normal: 'icons/home.png'
size_hint_x: None
width:50
BoxLayout:
size_hint_y: None
height: 500
spacing: 50
padding: 20
pos: root.x, (root.height-560)
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size_hint_y: None
orientation: "horizontal"
height: 50
spacing: 10
padding: 0
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
size_hint_x: None
size_hint_y: None
height: 50
width:100
text: 'Back'
on_release: root.manager.current = 'edit_device_groups_screen_5'
Button:
size_hint_x: None
size_hint_y: None
height: 50
width:100
text: 'Remove'
#have to change first argument, for now assume switch is on
on_press: root.remove()
on_release:root.manager.current = 'edit_device_groups_screen_5'
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#ffffff')
Rectangle:
pos: self.pos
size: self.size
#Devices connected
BoxLayout:
orientation: "horizontal"
canvas:
Color:
rgba: hex('#98a6b3')
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'Name:'
font_size: 24
#TODO
Label:
text: 'Group 1'
font_size: 24
#Devices connected
BoxLayout:
orientation: "horizontal"
canvas:
Color:
rgba: hex('#98a6b3')
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'Devices:'
font_size: 24
#TODO
Label:
text: '1,2,3,4'
font_size: 24
<HomeScreen>:
rows: 2
spacing: 10
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
BoxLayout:
size_hint_y: None
height: 50
spacing: 10
pos: root.x, (root.height-50)
# Make the background for the toolbar blue
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
on_press: root.manager.current = 'homescreen_1'
background_normal: 'icons/home.png'
size_hint_x: None
width:50
BoxLayout:
size_hint_y: None
height: 500
spacing: 50
padding: 50
pos: root.x, (root.height-560)
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
text: "Start"
font_size: 20
Button:
text: "Device Tester"
font_size: 20
Button:
text: "Connect Devices"
font_size: 20
Button:
text: "Edit Device Groups"
font_size: 20
on_press: root.manager.current = 'edit_device_groups_screen_5'
Button:
text: "Edit Group Behavior"
font_size: 20
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Label:
text: "Connected Devices"
font_size: 30
<EditDeviceGroupsScreen>:
rows: 2
spacing: 10
canvas:
Color:
rgba: 1,1,1,1
Rectangle:
pos: self.pos
size: self.size
#ToolBar
BoxLayout:
size_hint_y: None
height: 50
spacing: 10
pos: root.x, (root.height-50)
# Make the background for the toolbar blue
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
on_press: root.manager.current = 'homescreen_1'
background_normal: 'icons/home.png'
size_hint_x: None
width:50
BoxLayout:
size_hint_y: None
height: 500
spacing: 50
padding: 20
pos: root.x, (root.height-560)
BoxLayout:
orientation: "vertical"
spacing: 10
padding: 10
canvas:
Color:
rgba: hex('#0099cc')
Rectangle:
pos: self.pos
size: self.size
Button:
size_hint_x: None
size_hint_y: None
height: 50
size: self.size
text: 'create group'
on_press: root.create_group()
on_release: root.manager.current = 'group_template_screen_11'
#Groups holder
BoxLayout:
orientation: "vertical"
spacing: 5
padding: 5
canvas:
Color:
rgba: hex('#ffffff')
Rectangle:
pos: self.pos
size: self.size
#Adds Scrollability
ScrollView:
do_scroll_x:False
do_scroll_Y:True
BoxLayout:
id: glayout2
orientation: 'vertical'
spacing: 5
size_hint_y: None
height: self.minimum_height
<Manager>:
id: screen_manager
home_screen: home_screen
edit_device_groups_screen: edit_device_groups_screen
group_template_screen: group_template_screen
HomeScreen:
id: home_screen
name: 'homescreen_1'
manager: screen_manager
EditDeviceGroupsScreen:
id: edit_device_groups_screen
name: 'edit_device_groups_screen_5'
manager: screen_manager
GroupTemplateScreen:
id: group_template_screen
name: 'group_template_screen_11'
manager: screen_manager
#Output#
I have two files demo.py and demo.kv
I have a button +Add More which add row dynamic.I am trying to add vertical scrollbar in dynamic row using ScrollView:.But its not working properly.
its mean when i add row in scrollview that row having extra space in scrollview i want add rows without any spacing.
ScrollView:
BoxLayout:
orientation: "horizontal"
size_hint_y: None
height: 500
Rows:
id: rows
demo.py
import kivy
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)
class user(Screen):
def add_more(self):
self.ids.rows.add_row()
class Row(BoxLayout):
button_text = StringProperty("")
class Rows(BoxLayout):
orientation = "vertical"
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class Test(App):
def build(self):
self.root = Builder.load_file('demo.kv')
return self.root
if __name__ == '__main__':
Test().run()
demo.kv
<Button#Button>:
font_size: 15
font_name: 'Verdana'
<Label#Label>:
font_size: 15
font_name: 'Verdana'
<TextInput#TextInput>:
font_size: 15
font_name: 'Verdana'
padding_y: 3
<Row>:
GridLayout:
cols: 2
row_force_default: True
row_default_height: 40
Button:
text: root.button_text
size_hint_x: None
top: 200
Button:
text: 'World 1'
width: 300
user:
BoxLayout:
orientation: "vertical"
padding : 20, 5
BoxLayout:
orientation: "horizontal"
#padding : 10, 10
spacing: 10, 10
size: 450, 40
size_hint: None, None
Label:
size_hint_x: .2
text: "Test 1"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .8
text: "Test 2"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
BoxLayout:
orientation: "horizontal"
size_hint_y: None
height: 500
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
padding : 10, 5
spacing: 10, 10
size_hint: .5, .35
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
Button:
text: 'Cancel'
any help would be greatly appreciated.
If I have understood what you want, you have too many nested Layouts, that are unnecessary. Rows should be the main layout of your ScrollView.
On the other hand, Rows should always have the lowest possible height to contain their widgets (minimun_height property), not a fixed size.
Demo.py:
from kivy.uix.screenmanager import Screen
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
Window.clearcolor = (0.5, 0.5, 0.5, 1)
Window.size = (500, 400)
class User(Screen):
def add_more(self):
self.ids.rows.add_row()
class Row(BoxLayout):
button_text = StringProperty("")
class Rows(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
self.add_row()
def add_row(self):
self.row_count += 1
self.add_widget(Row(button_text=str(self.row_count)))
class Test(App):
def build(self):
self.root = Builder.load_file('Demo.kv')
return self.root
if __name__ == '__main__':
Test().run()
Demo.kv:
<Button#Button>:
font_size: 15
font_name: 'Verdana'
<Label#Label>:
font_size: 15
font_name: 'Verdana'
<TextInput#TextInput>:
font_size: 15
font_name: 'Verdana'
padding_y: 3
<Row>:
size_hint_y: None
height: self.minimum_height
height: 40
Button:
text: root.button_text
size_hint_x: None
top: 200
Button:
text: 'World 1'
width: 300
<Rows>:
size_hint_y: None
height: self.minimum_height
orientation: "vertical"
User:
BoxLayout:
orientation: "vertical"
padding : 20, 5
BoxLayout:
orientation: "horizontal"
#padding : 10, 10
spacing: 10, 10
size: 450, 40
size_hint: None, None
Label:
size_hint_x: .2
text: "Test 1"
text_size: self.size
valign: 'bottom'
halign: 'center'
Label:
size_hint_x: .8
text: "Test 2"
text_size: self.size
valign: 'bottom'
halign: 'center'
ScrollView:
Rows:
id: rows
BoxLayout:
orientation: "horizontal"
size_hint_x: .2
size_hint_y: .2
Button:
text: "+Add More"
on_press: root.add_more()
BoxLayout:
orientation: "horizontal"
padding : 10, 5
spacing: 10, 10
size_hint: .5, .35
pos_hint: {'x': .25, 'y':.25}
Button:
text: 'Ok'
Button:
text: 'Cancel'