kivy multiple instances of a screen with unique data - python

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.

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

How to push kivy widget to the top of the screen

Am having a hard time trying to align my widgets to the top of window in kivy, here is the pictorial represenation. My expectation is that adding an empty widget at the bottom would push the widgets to the top of the screen but it only gets to the middle of the screen. Any guidance will be helpful.
Layout
.kv file
#:import utils kivy.utils
#: import Window kivy.core.window.Window
<FlatButton#ButtonBehavior+Label>:
font_size: 14
<PosWindow>:
id: main_win
orientation: 'vertical'
canvas.before:
Color:
rgb: utils.get_color_from_hex('#ffffff')
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
spacing: 0
orientation: 'vertical'
#THE BEGINNNING OF THE TOP BAR
BoxLayout:
size_hint_y: None
height: 30
Label:
text: 'HEADER POSITION'
size_hint_x: .6
bold: True
color: (1,1,1,1)
canvas.before:
Color:
rgb: utils.get_color_from_hex('#5B2437')
Rectangle:
size: self.size
pos: self.pos
Label:
text: 'The Name'
size_hint_x: .4
height: 30
bold: True
color: (1,1,1,1)
canvas.before:
Color:
rgb: utils.get_color_from_hex('#5B2437')
Rectangle:
size: self.size
pos: self.pos
# THE END OF THE TOP BAR
#THE BEGINNING OF THE SECOND WAVE FULL
BoxLayout:
id: current
size_hint_y: None
height: 50
canvas.before:
Color:
rgba: (1,1,1, 1)
Rectangle:
size: self.size
pos: self.pos
Button:
text: 'Current Item:'
background_normal: ''
background_color: (.06, .32, .32, 1)
size_hint_x: .4
Button:
id: cur_product
text: 'Default Product'
background_normal: ''
background_color: (.06, .4, .4, 1)
Button:
id: cur_price
text: '0.00'
background_normal: ''
background_color: (.06, .65, .65, 1)
size_hint_x: .2
Widget: #To place everything at the top of the screen
#THE END OF THE SECOND WAVE FULL
#SEARCH FOR A PRODUCT
BoxLayout:
id: current
orientation: 'horizontal'
size_hint_y: None
height: 50
canvas.before:
Color:
rgba: (1,1,1, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint_x: .4
id: searchBox
canvas.before:
Color:
rgba: (.06, .75, .35, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint_x: .6
id: previewBox
canvas.before:
Color:
rgba: (.06, .35, .85, 1)
Rectangle:
size: self.size
pos: self.pos
Widget:
I found that as a little, I had to remove the first BoxLayout first the empty widgets except for the last boxlayout.
#:import utils kivy.utils
#: import Window kivy.core.window.Window
<FlatButton#ButtonBehavior+Label>:
font_size: 14
:
id: main_win
orientation: 'vertical'
canvas.before:
Color:
rgb: utils.get_color_from_hex('#ffffff')
Rectangle:
size: self.size
pos: self.pos
#THE BEGINNNING OF THE TOP BAR
BoxLayout:
size_hint_y: None
height: 30
Label:
text: 'HEADER POSITION'
size_hint_x: .6
bold: True
color: (1,1,1,1)
canvas.before:
Color:
rgb: utils.get_color_from_hex('#5B2437')
Rectangle:
size: self.size
pos: self.pos
Label:
text: 'The Name'
size_hint_x: .4
height: 30
bold: True
color: (1,1,1,1)
canvas.before:
Color:
rgb: utils.get_color_from_hex('#5B2437')
Rectangle:
size: self.size
pos: self.pos
#THE BEGINNING OF THE SECOND WAVE FULL
BoxLayout:
id: current
size_hint_y: None
height: 50
canvas.before:
Color:
rgba: (1,1,1, 1)
Rectangle:
size: self.size
pos: self.pos
Button:
text: 'Current Item:'
background_normal: ''
background_color: (.06, .32, .32, 1)
size_hint_x: .4
Button:
id: cur_product
text: 'Default Product'
background_normal: ''
background_color: (.06, .4, .4, 1)
Button:
id: cur_price
text: '0.00'
background_normal: ''
background_color: (.06, .65, .65, 1)
size_hint_x: .2
#THE END OF THE SECOND WAVE FULL
#SEARCH FOR A PRODUCT
BoxLayout:
id: current
orientation: 'horizontal'
size_hint_y: None
height: 50
canvas.before:
Color:
rgba: (1,1,1, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint_x: .4
id: searchBox
canvas.before:
Color:
rgba: (.06, .75, .35, 1)
Rectangle:
size: self.size
pos: self.pos
BoxLayout:
size_hint_x: .6
id: previewBox
canvas.before:
Color:
rgba: (.06, .35, .85, 1)
Rectangle:
size: self.size
pos: self.pos
Widget:

button and label text not showing

the two windows in the picture are exact copies(same line of code), only difference being that the right window is a screen inside a screen manager, but somehow the window on the right does not show the texts.
i'm not sure what the problem is and can't find anything related to it while doing research.
RIGHT WINDOW PYTHON FILE:
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.config import Config
space = ""
x = [(a * 9), (a*16)]
Config.set('graphics', 'width', x[0])
Config.set('graphics', 'height', x[1])
class MainScreen(Screen):
pass
class SecondScreen(Screen):
pass
class ThirdScreen(Screen):
pass
kv = Builder.load_file("main2.kv")
class ComplimentUI(App):
def build(self):
return kv
def change_screen(self, x):
scrnmanager = self.root.ids['sm']
scrnmanager.current = x
if __name__ == "__main__":
ComplimentUI().run()
RIGHT WINDOW BUILDER FILE:(main2.kv)
#:include secondscreen.kv
#:include thirdscreen.kv
<MainScreen>:
canvas.before:
Color:
rgb: .59, .74, .20
Rectangle:
size: self.size
pos: self.pos
FloatLayout:
TextInput:
pos_hint: {'center_x':1, 'top':.1}
size_hint: .1,.1
multiline: False
font_size: 20
font_name: "Dimbo Regular"
background_normal: ''
background_color: 0,0,0,0
Button:
text: "PLAY!"
pos_hint: {'center_x':.5, 'center_y':.3}
size_hint: .8, .17
font_name: "Splatch"
color: 0.15, .5, 0.2, 1
font_size: 0.14 * self.width
background_normal: ''
background_color: 0,0,0,0
on_press:
print("pressed, navigating to prev screen")
app.change_screen("screentwo")
root.manager.transition.direction = "left"
canvas.before:
Color:
rgb: 1,1, .8,1
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4,]
ScreenManager:
GridLayout:
cols: 1
ScreenManager:
id: sm
MainScreen:
name: "screenone"
id: screenone
SecondScreen:
name: "screentwo"
id: screentwo
ThirdScreen:
name: "thirdscreen"
id: thirdscreen[enter image description here][1]
LEFT WINDOW PYTHON FILE:
import kivy
from kivy.app import App
from kivy.lang import Builder
from kivy.config import Config
space = "";
x = [(a * 9), (a*16)]
Config.set('graphics', 'width', x[0])
Config.set('graphics', 'height', x[1])
kv = Builder.load_file("main.kv")
class MyMainApp(App):
def build(self):
return kv
if __name__ == "__main__":
MyMainApp().run()
LEFT WINDOW BUILDER FILE:(main.kv)
FloatLayout:
canvas.before:
Color:
rgb: .59, .74, .20
Rectangle:
size: self.size
pos: self.pos
TextInput:
pos_hint: {'center_x':1, 'top':.1}
size_hint: .1,.1
multiline: False
font_size: 20
font_name: "Dimbo Regular"
background_normal: ''
background_color: 0,0,0,0
Button:
text: "PLAY!"
pos_hint: {'center_x':.5, 'center_y':.3}
size_hint: .8, .17
font_name: "Splatch"
color: 0.15, .5, 0.2, 1
font_size: 0.14 * self.width
background_normal: ''
background_color: 0,0,0,0
on_press:
print("pressed, navigating to prev screen")
app.change_screen("screentwo")
root.manager.transition.direction = "left"
canvas.before:
Color:
rgb: 1,1, .8,1
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4,]
NEW EDIT:
as i pointed out in the comment below, the same problem happens with the FloatLayout of secondscreen.kv and thirdscreen.kv, if i put it inside the builder file of the left window, its normal. But when i put it inside a screen inside a screen manager(like the right window) it's gone. the same problem happens to all my screens. the reason i only put the mainscreen.kv is because its the shortest out of all the screens, but nonetheless i will still provide the files, but only 1 version of it (the one used for the right window) since they're basically the same lines. (only difference being the added first line for its class name and a slight indetation change to fit the levels)
SECONDSCREEN BUILDER FILE:
<SecondScreen>:
FloatLayout:
canvas.before:
Color:
rgb: .59, .74, .20
Rectangle:
size: self.size
pos: self.pos
TextInput:
pos_hint: {'center_x':.5, 'center_y':.56}
size_hint: .8, .3
multiline: False
font_size: 20
font_name: "Dimbo Regular"
background_normal: ''
background_color: 1, 1, .8, 1
Label:
pos_hint: {'center_x':.5, 'center_y':.76}
size_hint: .8, .07
text: "NAME!"
font_size: 0.8 * self.height
font_name: "kidsrock"
color: 0.15, .5, 0.2, 1
background_color: 0,0,0,0
canvas.before:
Color:
rgb: 1,1, .8,1
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4,]
Button:
text: "<<<"
size_hint: .28, .07
pos_hint: {'center_x':.24, 'center_y':.1}
font_name: "kidsrock"
color: 0.15, .5, 0.2, 1
font_size: 0.35 * self.width
background_normal: ''
background_color: 0,0,0,0
on_press:
print("pressed, navigating to prev screen")
app.change_screen("screenone")
root.manager.transition.direction = "right"
canvas.before:
Color:
rgb: 1,1, .8,1
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4,]
Button:
pos_hint: {'center_x':.8, 'center_y':.35}
size_hint: .2, .07
background_normal: ''
background_color: 0,0,0,0
color: 0.15, .5, 0.2, 1
text: "ENTER"
font_name: "kidsrock"
font_size: 0.25 * self.width
on_press:
print("pressed, navigating to next screen")
app.change_screen("thirdscreen")
root.manager.transition.direction = "left"
canvas.before:
Color:
rgb: 1,1, .8,1
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4,]
THIRDSCREEN BUILDER FILE:
<ThirdScreen>:
FloatLayout:
canvas.before:
Color:
rgb: .59, .74, .20
Rectangle:
size: self.size
pos: self.pos
TextInput:
pos_hint: {'center_x':1, 'top':.1}
size_hint: .1, .1
multiline: False
font_size: 20
font_name: "Dimbo Regular"
background_normal: ''
background_color: 0, 0, 0, 0
Label:
pos_hint: {'center_x':.5, 'center_y':.71}
size_hint: .8, .17
text: "COMPLIMENT!"
font_size: 20
font_name: "kidsrock"
color: 0.15, .5, 0.2, 1
background_color: 0,0,0,0
canvas.before:
Color:
rgb: 1,1, .8,1
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4,]
Button:
pos_hint: {'center_x':.24, 'center_y':.1}
size_hint: .28, .07
font_name: "kidsrock"
color: 0.15, .5, 0.2, 1
font_size: 0.35 * self.width
text: "<<<"
background_normal: ''
background_color: 0,0,0,0
on_press:
print("pressed, navigating to prev screen")
app.change_screen("screentwo")
root.manager.transition.direction = "right"
canvas.before:
Color:
rgb: 1,1, .8,1
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4,]
NEW- NEW EDIT!:
UPDATE
after restarting my computer, it now looks like this.
Root Cause - Button & Label text not showing
The most probable cause is that the default color for text is white ([1, 1, 1, 1]), and the background color for both widgets are also white. You need to set the text color to non-white e.g. black ([0, 0, 0, 1]).
TextInput Box - not showing
The TexInput box is not visible in both windows (left & right) because of background_normal: '' and background_color: 0,0,0,0.
Comment them off and the TextInput box will be visible.
Button's text, 'PLAY' - not showing in right window
It could be something in the include kv files e.g. secondscreen.kv, and/or thirdscreen.kv that are/is causing the visibility. Comment off both kv files to trouble shoot the problem.
Example
The following example of the right window i.e. using ScreenManager is able to display the Button's text, "PLAY" and also the TextInput box.
main-right.py
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
class MainScreen(Screen):
pass
class SecondScreen(Screen):
pass
class ThirdScreen(Screen):
pass
kv = Builder.load_string("""
# :include secondscreen.kv
# :include thirdscreen.kv
<MainScreen>:
canvas.before:
Color:
rgb: .59, .74, .20
Rectangle:
size: self.size
pos: self.pos
FloatLayout:
TextInput:
hint_text: 'Type here'
pos_hint: {'center_x':1, 'top':.1}
size_hint: .1,.1
multiline: False
font_size: 20
# font_name: "Dimbo Regular"
# background_normal: ''
# background_color: 0,0,0,0
Button:
text: "PLAY!"
pos_hint: {'center_x':.5, 'center_y':.3}
size_hint: .8, .17
#font_name: "Splatch"
color: 0.15, .5, 0.2, 1
font_size: 0.14 * self.width
background_normal: ''
background_color: 0,0,0,0
on_press:
print("pressed, navigating to prev screen")
app.change_screen("screentwo")
root.manager.transition.direction = "left"
canvas.before:
Color:
rgba: 1, 1, .8, 1
RoundedRectangle:
size: self.size
pos: self.pos
radius: [4,]
GridLayout:
cols: 1
ScreenManager:
id: sm
MainScreen:
name: "screenone"
id: screenone
SecondScreen:
name: "screentwo"
id: screentwo
ThirdScreen:
name: "thirdscreen"
id: thirdscreen
""")
class RightWindow(App):
title = "ComplimentUI"
def build(self):
return kv
if __name__ == "__main__":
RightWindow().run()
Output
I was facing a similar problem and the bug for me turned out to be a declaration of size_hint_x for the button. Once I removed that, the text was visible.

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