Gridlayout height based on Label height in recycleview not aligned - python

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)

Related

Kivy: Having trouble getting two Recycleviews to show up in my Kivy application

I'm working on a kivy application. I create two recycleViews, both pull data from a database table and I want the data to be displayed under the two recycleviews.
I've created the following .kv file:
#:kivy 2.1.0
<SelectableUserBoxLayout>:
# Draw a background to indicate selection
font_size: '26sp'
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
userid: ""
uniqueid: ""
displayname: ""
status: ""
permissionid: ""
GridLayout:
cols:5
Label:
text: root.userid
Label:
text: root.uniqueid
Label:
text: root.displayname
Label:
text: root.status
Label:
text: root.permissionid
<SelectableUserBoxLayout>:
# Draw a background to indicate selection
font_size: '26sp'
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
resid: ""
startTime: ""
endTime: ""
userId: ""
lockerId: ""
GridLayout:
cols:5
Label:
text: root.resid
Label:
text: root.startTime
Label:
text: root.endTime
Label:
text: root.userId
Label:
text: root.lockerId
<UserListView>:
id: userlist
viewclass: 'SelectableUserBoxLayout'
SelectableUserRecycleBoxLayout:
id: controller
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
font_size: '26sp'
<ReservationListView>:
#id: reservationlist
viewclass: 'SelectableReservationBoxLayout'
SelectableReservationRecycleBoxLayout:
id: rescontroller
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
font_size: '26sp'
<ManagementScreen>:
name: 'managementscreen'
#id: management_screen
BoxLayout:
orientation: 'vertical'
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: './assets/background.png'
Label:
font_size: '26sp'
size_hint_y: 0.1
text: 'Management Screen'
GridLayout:
cols: 3
size_hint_y: 0.9
spacing: 10
padding: 10
GridLayout:
rows: 2
GridLayout:
size_hint_y: .15
cols:5
canvas.before:
Color:
rgba: (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'UserID'
Label:
text: 'UniqueIdentifier'
Label:
text: 'DisplayName'
Label:
text: 'Status'
Label:
text: 'PermissionID'
UserListView:
id: recview
key_selection: 'selectable'
size_hint_x: .4
GridLayout:
rows:2
GridLayout:
size_hint_y: .15
cols:5
canvas.before:
Color:
rgba: (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'ReservationID'
Label:
text: 'StartTime'
Label:
text: 'EndTime'
Label:
text: 'UserID'
Label:
text: 'LockerID'
ReservationListView:
id: resrecview
key_selection: 'selectable'
size_hint_x: .4
GridLayout:
size_hint_x: .2
rows: 4
spacing: 0
padding: 0
Button:
text: 'Verwijder'
font_size: '26sp'
on_release: recview.delete_user()
Button:
text: 'Laad CSV'
font_size: '26sp'
Button:
text: 'Reserveringen'
font_size: '26sp'
These are the relevant Recycleviews:
class UserListView(RecycleView):
def __init__(self, **kwargs):
super(UserListView, self).__init__(**kwargs)
self.data = [{"userid": str(x[0]),"uniqueid": x[1], "displayname": str(x[2]), "status": str(x[3]), "permissionid": str(x[4]), "selected":False} for x in database.get_all_users()]
class ReservationListView(RecycleView):
def __init__(self, **kwargs):
super(ReservationListView, self).__init__(**kwargs)
self.data = [{"resid": str(x[0]),"startTime": x[1], "endTime": str(x[2]), "userId": str(x[3]), "lockerId": str(x[4]), "selected":False} for x in database.get_all_reservations()]
while the colums show correctly, the data under the colums aren't. To illustrate (mind that my application runs on a raspberry pi with a custom screen):
As you can see, my columns load correctly, and the first recycleview loads userdata from the database. The data, however isn't lined up properly. My second recycleview loads reservation data from the database. When I tap under the column, my screen shows data being clicked, but isn't displayed correctly in the recycleview.
My questions:
How can I get the data to line up correctly to my colums?
How can I get the data under my second column to be displayed correctly?
Edit: Seems like I've used SelectableUserBoxLayout twice. That explains a lot! I've rewritten my .kv file and it now works the way I want.
my new .kv file:
#:kivy 2.1.0
<SelectableUserBoxLayout>:
# Draw a background to indicate selection
font_size: '26sp'
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
userid: ""
uniqueid: ""
status: ""
permissionid: ""
GridLayout:
cols:4
Label:
text: root.userid
size_hint_x: .1
Label:
text: root.uniqueid
size_hint_x: .6
Label:
text: root.status
size_hint_x: .1
Label:
text: root.permissionid
size_hint_x: .2
<SelectableReservationBoxLayout>:
# Draw a background to indicate selection
font_size: '26sp'
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3) if self.selected else (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
resid: ""
startTime: ""
endTime: ""
userId: ""
lockerId: ""
GridLayout:
cols:5
Label:
text: root.resid
size_hint_x: .2
Label:
text: root.startTime
size_hint_x: .3
Label:
text: root.endTime
size_hint_x: .3
Label:
text: root.userId
size_hint_x: .1
Label:
text: root.lockerId
size_hint_x: .1
<ReservationListView>:
viewclass: 'SelectableReservationBoxLayout'
SelectableReservationRecycleBoxLayout:
id: rescontroller
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
font_size: '26sp'
<UserListView>:
viewclass: 'SelectableUserBoxLayout'
SelectableUserRecycleBoxLayout:
id: controller
default_size: None, dp(56)
default_size_hint: 1, None
size_hint_y: None
height: self.minimum_height
orientation: 'vertical'
multiselect: True
touch_multiselect: True
font_size: '26sp'
<ManagementScreen>:
name: 'managementscreen'
id: management_screen
BoxLayout:
orientation: 'vertical'
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: './assets/background.png'
Label:
font_size: '26sp'
size_hint_y: 0.1
text: 'Management Screen'
GridLayout:
cols: 3
spacing: 10
padding: 10
GridLayout:
cols: 1
size_hint_x: .45
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3)
Rectangle:
pos: self.pos
size: self.size
GridLayout:
size_hint_y: .15
cols: 4
canvas.before:
Color:
rgba: (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'UserID'
size_hint_x: .1
Label:
text: 'UniqueIdentifier'
size_hint_x: .6
Label:
text: 'Status'
size_hint_x: .1
Label:
text: 'PermissionID'
size_hint_x: .2
UserListView:
id: userview
size_hint_y: .85
GridLayout:
cols: 1
size_hint_x: .45
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3)
Rectangle:
pos: self.pos
size: self.size
GridLayout:
size_hint_y: .15
cols: 5
canvas.before:
Color:
rgba: (0, 0, 0, 1)
Rectangle:
pos: self.pos
size: self.size
Label:
text: 'ReservationID'
size_hint_x: .2
Label:
text: 'StartTime'
size_hint_x: .3
Label:
text: 'EndTime'
size_hint_x: .3
Label:
text: 'UserID'
size_hint_x: .1
Label:
text: 'LockerID'
size_hint_x: .1
ReservationListView:
id: resview
size_hint_y: .85
GridLayout:
rows: 3
size_hint_x: .1
canvas.before:
Color:
rgba: (.0, 0.9, .1, .3)
Rectangle:
pos: self.pos
size: self.size
Button:
text: 'Verwijder'
font_size: '26sp'
on_release: userview.delete_user()
Button:
text: 'Laad CSV'
font_size: '26sp'
Button:
text: 'Reserveringen'
font_size: '26sp'
This question can be closed.

KivyMD Text Field doesn't work, recieve attribute error when pressing clear button and MD Cards arent aligned properly

I completed my code for main window which is the login page and I'm writing my code for the second page. Then, I tried to use the text field on my login screen and I can't type in it. However, before making my second window, the text field worked as expected and I can type in it. What could cause this issue?
Furthermore, I recieve an error (AttributeError: 'super' object has no attribute 'getattr'
) when I tried to press the clear button in main window.
Also, if you tried to run this code and see the second window, you will notice 3 MD cards not aligned properly if you don't expand the window to full size. if you have any idea how to fix it, please let me know.
SUMMARY OF WHAT I'M TRYING TO ACHIEVE HERE:
Figure out what why I can't use the textfield in main window
Fix the error when press the clear button
Align MD Cards properly
.py file
from kivy.lang import Builder
from kivymd.app import MDApp
from kivy.uix.screenmanager import ScreenManager, Screen
class MainWindow(Screen):
pass
class SecondWindow(Screen):
pass
class WindowManager(ScreenManager):
pass
class BaseApp(MDApp):
def build(self):
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_palette = "Green"
return Builder.load_file("base.kv")
def clear(self):
self.root.ids.user.text = ""
self.root.ids.passw.text = ""
if __name__ == "__main__":
BaseApp().run()```
.kv file
# Filename: base.kv
#:kivy 2.1.0
#:include main.py
WindowManager:
MainWindow:
SecondWindow:
<MainWindow>:
name: "main"
Screen:
MDCard:
size_hint: None, None
size: 400, 500
pos_hint: {"center_x": 0.5, "center_y": 0.5}
elevation: 10
padding: 25
spacing: 25
orientation: "vertical"
MDLabel:
id: login_label
text: "WELCOME TO JAMES MADISON/n HIGH SCHOOL STUDENTS APP"
font_size: 22
font_name: "Raleway-Regular"
halign: "center"
size_hint_y: None
height: self.texture_size[1]
padding_y: 15
MDBoxLayout:
Image:
source: "jmhs.png"
size_hint_x: 1.15
halign: "center"
size_hint_y: 1.15
height: self.texture_size[1]
padding_y: 10
MDTextFieldRound:
id: user
hint_text: "Username"
icon_right: "account"
size_hint_x: None
width: 200
font_size: 18
font_name: "Roboto-Regular"
pos_hint: {"center_x": 0.5}
MDTextFieldRound:
id: passw
hint_text: "Password"
icon_right: "eye-off"
size_hint_x: None
width: 200
font_size: 18
font_name: "Roboto-Regular"
pos_hint: {"center_x": 0.5}
password: True
MDRoundFlatButton:
text: "LOG IN"
font_size: 12
font_name: "Raleway-Regular"
pos_hint: {"center_x": 0.5}
on_press:
app.root.current = "second"
root.manager.transition.direction = "left"
MDRoundFlatButton:
text: "CLEAR"
font_size: 12
font_name: "Raleway-Regular"
pos_hint: {"center_x": 0.5}
on_press: app.clear()
<SecondWindow>:
name: "second"
MDBoxLayout:
orientation: "horizontal"
MDBoxLayout:
size_hint: .225, 1
canvas.before:
Color:
rgba: 0, 0, 0, 0
Rectangle:
pos: self.pos
size: self.size
MDBoxLayout:
orientation: "vertical"
spacing: "10dp"
size_hint: 1, 1
canvas.before:
Color:
rgba: 227/255, 255/255, 226/255, 0.8
Rectangle:
pos: self.pos
size: self.size
MDBoxLayout:
spacing: "10dp"
size_hint: 1, .1
MDBoxLayout:
spacing: "10dp"
size_hint: 1, .9
canvas.before:
Color:
rgba: 227/255, 255/255, 226/255, 0.8
Rectangle:
pos: self.pos
size: self.size
MDGridLayout:
cols: 3
padding: 18
spacing: "20dp"
MDCard:
padding: 16
elevation: 0
border_radius: 20
radius: [15]
size_hint: None, None
size: "370dp", "140dp"
pos_hint: {"center_x": .5, "center_y": .5}
MDCard:
padding: 16
elevation: 0
border_radius: 20
radius: [15]
size_hint: None, None
size: "370dp", "140dp"
pos_hint: {"center_x": .5, "center_y": .5}
MDCard:
padding: 16
elevation: 0
border_radius: 20
radius: [15]
size_hint: None, None
size: "200dp", "140dp"
pos_hint: {"center_x": .5, "center_y": .5}
MDBoxLayout:
size_hint: .29, 1
canvas.before:
Color:
rgba: 0, 0, 0, 0
Rectangle:
pos: self.pos
size: self.size

kivy: Aligning images to boxes

I am trying to align the Images to by Buttons so such that each image has a button placed down below. My current problem is that it does not align properly which I assume has to relate with my the columns specified within my GridLayout. Here is my code for my.kv:
<ScreenManagement>:
MenuScreen:
id: name
name: 'menu'
<MenuScreen>:
BoxLayout:
BoxLayout:
canvas:
Color:
rgba: 184/255, 200/255, 202/255, 1
Rectangle:
pos: self.pos
size: self.size
GridLayout:
cols: 3
rows: 4
BoxLayout:
orientation: 'horizontal'
spacing: 15
padding: 10
Image:
source: 'img/image1.jpg'
padding :10
size_hint_x: 0.2
allow_stretch: True
Image:
source: 'img/image2.jpg'
padding: 10
size_hint_x: 0.2
width: 2
allow_stretch: True
Image:
source: 'img/image3.jpg'
size_hint_x: 0.2
allow_stretch: True
Button:
size_hint_y: None
pos: (10,150)
size_hint: None, None
size: 250,50
spacing: 50
#padding: (0, 10, 0, 0)
text: 'button2image1'
on_press: self.background_color = 0,168/255,137/255,1
on_release:
root.manager.current = 'watermelon'
Button:
size_hint_y: None
pos: (275, 150)
size_hint: None, None
size: 250,50
spacing: 50
text: 'button2image2'
on_press: self.background_color = 0,168/255,137/255,1
on_release:
root.manager.current = 'galia'
Button:
size_hint_y: None
size: 250,50
size_hint: None, None
pos: (537.5, 150)
text: 'button2image3'
on_press: self.background_color = 0,168/255,137/255,1
on_release:
root.manager.current = 'cantaloupe'

kivy multiple instances of a screen with unique data

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.

Python/Kivy : How to put dynamic label widget and value

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'

Categories

Resources