Kivy expand and collapse a panel to hide the inside itens - python

I'm new to kivy and I am trying do create a widget to colapse and expand after click in a button. When it is colapsed the inside widgets must be hidden, and when it is extended the height should be minimum heigh possible.
I did this implementation, but when expanded i couldn't set the height properly, and the childrens don't hide when colapse...
I know that already there is a widget that do this in kivyMD library, but I need create a differente layout for the button and the childrens, so if someone could help me...
kivy file: teeeste.kv
#:import C kivy.utils.get_color_from_hex
<CLabel#Label>:
color: 0,0,0,1
size_hint_y: None
height: 40
<CButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: C("#455A64") if self.state == "normal" else (0.26,0.26,0.26,0.85)
RoundedRectangle:
pos: self.pos
size: self.size
radius: 10,10,10,10
size_hint: None,None
size: 300,40
<Box#GridLayout>:
canvas.before:
Color:
rgba: 1,1,1,1
RoundedRectangle:
size: self.size
pos: self.pos
radius: 10,10,10,10
cols: 1
size_hint: None,None
width: 300
height: self.minimum_height
orientation: "tb-lr"
FloatLayout:
AnchorLayout:
anchor_x: "center"
anchor_y: "top"
padding: 0,30,0,0
Box:
id: box
CButton:
text: "Press to expand or colapse"
on_release: box.height = 300 if box.height == 40 else 40
CLabel:
text: "abc"
CLabel:
text: "abc"
CLabel:
text: "abc"
CLabel:
text: "abc"
python file:
# coding: utf-8
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.utils import get_color_from_hex
Window.clearcolor = get_color_from_hex("#424242")
class TesteApp(App):
def build(self):
return aplicativo
aplicativo = Builder.load_file("teeeste.kv")
if __name__ == "__main__":
TesteApp().run()
I did the changes suggested by #JohnAnderson and I tried implement other Box inside each other, but sometimes after click on "NUMBER 3" button the childrens inside the related box stop of expand.
Here is the actual code:
kivy: teeeste.ky
#:import C kivy.utils.get_color_from_hex
<CLabel#Label>:
color: 0,0,0,1
size_hint_y: None
height: 40
<CButton>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: C("#455A64") if self.state == "normal" else (0.26,0.26,0.26,0.85)
RoundedRectangle:
pos: self.pos
size: self.size
radius: 10,10,10,10
size_hint: 1.0,None
height: 40
<Box#GridLayout>:
canvas.before:
Color:
rgba: 1,1,1,1
RoundedRectangle:
size: self.size
pos: self.pos
size_hint: 0.8,None
height: self.minimum_height
FloatLayout:
AnchorLayout:
anchor_x: "center"
anchor_y: "top"
padding: 0,30,0,0
ScrollView:
do_scroll_x: False
size_hint: None, 0.9
width: 300
GridLayout:
cols: 1
spacing: 5
size_hint_y: None
height: self.minimum_height
Box:
id: box
cols: 1
CButton:
text: "NUMBER 1"
on_release: self.exp_or_collapse(box)
CLabel:
text: "aaa"
Box:
id: box2
cols: 1
CButton:
text: "NUMBER 2"
on_release: self.exp_or_collapse(box2)
CLabel:
text: "bbb"
Box:
id: box3
cols: 1
CButton:
text: "NUMBER 03"
on_release: self.exp_or_collapse(box3)
Box:
id: box4
cols: 1
CButton:
text: "CHILD 1"
on_release: self.exp_or_collapse(box4)
CLabel:
text: "111"
Box:
id: box5
cols: 1
CButton:
text: "CHILD 2"
on_release: self.exp_or_collapse(box5)
CLabel:
text: "222"
Box:
id: box6
cols: 1
CButton:
text: "CHILD 3"
on_release: self.exp_or_collapse(box6)
CLabel:
text: "333"
Box:
id: box7
cols: 1
CButton:
text: "CHILD 4"
on_release: self.exp_or_collapse(box7)
CLabel:
text: "444"
Box:
id: box8
cols: 1
CButton:
text: "CHILD 5"
on_release: self.exp_or_collapse(box8)
CLabel:
text: "555"
Box:
id: box9
cols: 1
CButton:
text: "CHILD 6"
on_release: self.exp_or_collapse(box9)
CLabel:
text: "666"
Box:
id: box10
cols: 1
CButton:
text: "CHILD 7"
on_release: self.exp_or_collapse(box10)
CLabel:
text: "777"
Box:
id: box11
cols: 1
CButton:
text: "CHILD 8"
on_release: self.exp_or_collapse(box11)
CLabel:
text: "888"
Box:
id: box12
cols: 1
CButton:
text: "CHILD 9"
on_release: self.exp_or_collapse(box12)
CLabel:
text: "999"
Python file: main.py
import kivy
kivy.require("1.11.0")
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.button import Button
class CButton(Button):
def exp_or_collapse(self, id):
if id.height == self.height:
# expand:
for child in id.children:
child.height = 40
child.opacity = 1
else:
# collapse
for child in id.children:
if child != self:
child.height = 0
child.opacity = 0
class expApp(App):
def build(self):
return Builder.load_file("exp.kv")
if __name__ == "__main__":
expApp().run()
Imagage of the all box colapsed

One way to do that is to write a method to do it in the CButton class:
class CButton(Button):
def exp_or_collapse(self, box):
if box.height == self.height:
# expand
for child in box.children:
child.height = 40
child.opacity = 1
else:
# collapse
for child in box.children:
if child != self:
child.height = 0
child.opacity = 0
Then use that in the kv file:
FloatLayout:
AnchorLayout:
anchor_x: "center"
anchor_y: "top"
padding: 0,30,0,0
Box:
id: box
CButton:
text: "Press to expand or colapse"
on_release: self.exp_or_collapse(box)
CLabel:
text: "abc"
CLabel:
text: "abc"
CLabel:
text: "abc"
CLabel:
text: "abc"
The opacity fiddling is required to completely hide the CLabels, since a Label will display its text even if its size is 0.
The above code is designed to handle only CLabels and CButtons in a Box. To expand it to handle general children of the Box, the exp_or_collapse() can be modified as:
class CButton(Button):
removedChildren = ListProperty([])
def exp_or_collapse(self, id):
if len(self.removedChildren) > 0:
# expand:
# re-add all children
self.removedChildren.reverse()
for child in self.removedChildren:
id.add_widget(child)
self.removedChildren = []
else:
# collapse
# remove all children (except ourself)
for child in id.children:
if child != self:
self.removedChildren.append(child)
for child in self.removedChildren:
id.remove_widget(child)

Related

Horizontally aligning buttons in kivy

This is how my program looks right now.
How can I position my button "Log in" to always be horizontally aligned with center? I've tried looking on Stack Overflow about similar stuff but nothing worked for me... If anyone can help me, I would be really thankful.
Here's my python code:
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.gridlayout import GridLayout
import kivy.properties as kyprops
from kivy.uix.widget import Widget
from kivy.uix.image import Image
Builder.load_file("main.kv")
Window.clearcolor = (1,1,1,1)
# Declare both screens
class LoginScreen(Screen):
#txt_inpt = kyprops.ObjectProperty(None)
#def __init__(self):
pass
class InfoScreen(Screen):
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(LoginScreen(name='Login'))
sm.add_widget(InfoScreen(name='Info'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
Here is my .kv code:
#:import C kivy.utils.get_color_from_hex
<LoginScreen>:
RelativeLayout:
txt_inpt: txt_inpt
canvas:
Color:
rgba: C('#336699')
Line:
width: 2
rectangle: (0,self.height-50,self.width,0)
id: linija
Ellipse:
pos: self.width- 35, self.height-15
size: 7 , 7.0000000001
angle_start: 0
angle_end: 360
Ellipse:
pos: self.width- 35, self.height-27
size: 7 , 7.0000000001
angle_start: 0
angle_end: 360
Ellipse:
pos: self.width- 35, self.height-39
size: 7 , 7.0000000001
angle_start: 0
angle_end: 360
TextInput:
id: txt_inpt
password: True
multiline: False
hint_text: 'Username'
hint_text_color: C('#b3ccff')
size_hint_x: 0.9
size_hint_y: None
pos_hint: {"x":0.05, "top":0.8}
background_color: (1,1,1,0.2)
on_text_validate: root.manager.current = 'Info'
height: 30
pos: 300,60
TextInput:
id: txt_inpt
password: True
multiline: False
hint_text: 'Password'
hint_text_color: C('#b3ccff')
size_hint_x: 0.9
size_hint_y: None
pos_hint: {"x":0.05, "top":0.7}
background_color: (1,1,1,0.2)
on_text_validate: root.manager.current = 'Info'
height: 30
pos: 300,60
BoxLayout:
width: 1
pos: self.parent.pos # important!
orientation: 'vertical'
halign: 'center'
Button:
on_press: root.manager.current = 'Info'
background_color: C('#336699')
pos: self.pos
size: self.size
size: 80,30
size_hint: None, None
## NOTE: pos_hint: {"x":0.45, "top":0.6}
font_name: 'Droid.otf'
text: 'Log in'
<InfoScreen>:
BoxLayout:
Button:
text: 'My settings button'
Button:
text: 'Back to menu'
on_press: root.manager.current = 'Login'
Your line in kv:
pos: self.parent.pos # important!
is positioning the BoxLayout in the lower left corner of the RelativeLayout
You can center it by using pos_hint and minimum_width:
BoxLayout:
# width: 1
# pos: self.parent.pos # important!
pos_hint: {'center_x':0.5, 'y':0}
size_hint_x: None
width: self.minimum_width
orientation: 'vertical'

Spinner, ToggleButton store value and print when pressing Button

I'm pretty new to python and kivy and I'm trying to build my first app for my masterthesis. The problem I'm struggeling with right now is that I have multiple python and kivy files, and my app includes a group of Toggle buttons and Spinners. I want to 'store'/assign theselected values and print them when i hit my submit button. I'm working with multiple python and kivy files. The app also has some sliders and i managed to get those values when pressing submit, but can't figure it out for toggles nor spinners. I hope you can help!:)
Main .py, rather important:
import kivy
from kivy.app import App
from kivy.uix.button import Label
from kivy.uix.widget import Widget
from kivy.uix.textinput import TextInput
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import BooleanProperty
from kivy.properties import ObjectProperty
Builder.load_file('Header.kv')
Builder.load_file('Statusbar.kv')
Builder.load_file('Inputparameters.kv')
Builder.load_file('Outputparameters.kv')
#Layout
class Peenomat(AnchorLayout):
def show_selected_value(self, spinner, text):
print(spinner, text)
#pass
#DropDown in Inputparameters
#class InputParameters(BoxLayout):
#state = BooleanProperty(False)
class PeenomatApp(App):
def build(self):
return Peenomat()
if __name__=="__main__":
PeenomatApp().run()
The main kv file:
AnchorLayout:
anchor_x: 'left'
anchor_y: 'bottom'
GridLayout:
cols: 1
canvas.before:
Color:
rgba: 0.75 ,0.75, 0.75, 1
Rectangle:
pos: self.pos
size: self.size
Header:
id: _header
size_hint: 1, 0.1
#height: 100
InputParameters:
id:_input_parameters
size_hint: 1, 0.45
StatusBar:
id:_status_bar
size_hint: 1, 0.1
#height: 50
OutputParameters:
id:_output_parameters
size_hint: 1, 0.35
The .kv file that includes the toogle buttons, spinners, and sliders where i guess most of the implemantation needs to be done
#: import statusbar StatusBar
<InputParameters#GridLayout>
prozess: _proz_value
prozess1: _prozess1
prozess2: _prozess2
prozess3: _prozess3
vorbehandlung: _vorbehandlung
material: _material
haerte: _haerte
rauheit: _rauheit
cols: 2
padding: 15
spacing: 15
#Farbe Schrift Label
cb: (1,1, 1,1)
#Farbe Slider
cs: (0,0.353, 0.663,1)
#FontSize
fs: 20
#Prozess
Label:
text:'Prozess: '
bold: True
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
BoxLayout:
orientation: 'horizontal'
id: _proz_value
_proz_value: 0
ToggleButton:
text:'P-MOH'
id: _prozess1
group: "proc_group"
background_color: 0.0, 0.353, 0.663, 1.0
bold: True
on_press: root._proz_value = 1
ToggleButton:
text:'E-MOH'
id: _prozess2
group: "proc_group"
background_color: 0.0, 0.353, 0.663, 1.0
bold: True
on_press: root._proz_value = 2
ToggleButton:
text:'PE-MOH'
id: _prozess3
group: "proc_group"
background_color: 0.0, 0.353, 0.663, 1.0
bold: True
on_press: root._proz_value = 3
#Material
Label:
text: 'Material: '
bold: True
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
Spinner:
id: _material
# Callback
on_text:
text: "Auswahl treffen"
bold:True
values: ['1.2379', 'Gusseisen', 'Kautschuk', 'Carbon', 'Adamantium']
#background_normal: '[1,1,1,1]'
background_color: root.cs
color: root.cb
# Herstellschritte
Label:
text:'Fertigungsschritte: '
bold: 'True'
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
Spinner:
id: _vorbehandlung
# Callback
on_text:
app.root.show_selected_value(self, self.text)
text: "Auswahl treffen"
bold:True
values: ['Fräsen', 'Erodieren', 'Schleifen', 'Polieren']
#background_normal: '[1,1,1,1]'
background_color: root.cs
color: root.cb
# Haerte
Label:
text:'Haerte: '
bold: True
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
BoxLayout:
orientation: 'vertical'
spacing: 15
Label:
text: str(_haerte.value) + ' HRC'
color: root.cs
bold: True
Slider:
id: _haerte
min: 45
max: 65
value:55
step: 1
value_track: True
value_track_color: root.cs
# Rauheit
Label:
text:'Rauheit: '
#color: cb
bold: True
font_size: root.fs
text_size: self.size
halign: 'left'
valign: 'center'
color: root.cb
BoxLayout:
orientation: 'vertical'
spacing: 15
Label:
text: str("%.1f" % _rauheit.value) + ' Rz' #eine Nachkommastelle
color: root.cs
bold: True
Slider:
id: _rauheit
min: 1
max: 10
value:5.5
step: 0.1
value_track: True
value_track_color: root.cs
The .kv file that includes the submit button:
#: import statusbar StatusBar
<StatusBar#BoxLayout>
orientation:'horizontal'
padding: 5
fs: 16
Button:
text: 'Clear'
background_color: 0.0, 0.353, 0.663, 1.0
size_hint: 0.4, 1
bold: True
font_size: 20
on_press: root.btn_clear()
Button:
text: 'Submit'
background_color: 0.0, 0.353, 0.663, 1.0
size_hint: 0.4, 1
bold: True
font_size: 20
on_press: root.btn_submit()
and last but not the least the file that includes the methods that are assigned to the buttons, which shuld also be important for my issue:
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ObjectProperty
from kivy.app import App
from kivy.lang import Builder
class StatusBar(BoxLayout):
group_mode = False
#translation = ListProperty(None)
prozess = ObjectProperty(None)
vorbehandlung = ObjectProperty(None)
material = ObjectProperty(None)
haerte = ObjectProperty(None)
rauheit = ObjectProperty(None)
def btn_submit(self,text):
ip = App.get_running_app().root.ids._input_parameters
print("Haerte:", ip.haerte.value, "Rauheit:", ip.rauheit.value, "Material:", ip.material.text)
def btn_clear(self):
np = App.get_running_app().root.ids._input_parameters
np.prozess1.state = "normal"
np.prozess2.state = "normal"
np.prozess3.state = "normal"
np.material.text = "Auswahl treffen"
np.haerte.value = 55
np.rauheit.value = 5.5
The App is running like this and the clear button is exactly doing what its supposed to do, but I really can't figure out how I manage to print the selected spinner and toggle values when hitting submit...I hope you guys can help, been struggeling with this since a while now. Thanks in advance!
Alright i figured out an easy way to get the spinner value when hititng submit:
def btn_submit(self):
ip = App.get_running_app().root.ids._input_parameters
print("Haerte:", ip.haerte.value, "Rauheit:", ip.rauheit.value, "Material:", ip.material.text, "Vorbehandlung:", ip.vorbehandlung.text)
to get the value of the toggle buttons i did this:
def on_state(self, togglebutton):
tb = togglebutton
if tb.state == 'down':
self.verfahren = tb.text
InputParameters.verfahren = tb.text
print(self.verfahren)
return InputParameters.verfahren
and added in the .kv file for the toggle button:
ToggleButton:
id:_prozess2
text:'E-MOH'
on_state: root.on_state(self)
I'm getting the value/state like that, but it's not triggered with the submit button, can't figure out how to do so

Why is Screens not loading in Kv Language?

I have an App with three toggle buttons in a fixed header that is an outside indented layout for screen manager. On initialisation, the Import screen must show i.e. self.ids.scrn_man.current = 'import_scn" and when a toggle button is pushed a next screen should show i.e. on_state: scrn_man.current = "settings_scrn".
But for some reason, only the header is showing and the screens do not want to transition. I don't get any errors.
I tried different layouts as my Apps main class inheritance including, FloatLayout, StackLayout and BoxLayout. I also made the header fixed with AnchorLayout and use a different layout as the inline layout for ScreenManager. If I remove the ScreenManager I see my widgets, but of course, I cannot transition. I did at first try using TabbedPanel to house my different widgets but I encountered a constant RefError: weak object reference if I added too many widgets (but that's not for now). So I re-designed with something I knew worked on a previous App albeit less complex.
Here is my faulty code:
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.stacklayout import StackLayout
from kivy.uix.togglebutton import ToggleButton
from kivy.lang import Builder
from kivy.uix.popup import Popup
from kivy.properties import StringProperty, ObjectProperty
Builder.load_string("""
<RoundedButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (1,.6,0,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<RoundedCancelButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (1,.2,.2,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<RoundedAcceptButton#Button>:
background_color: 0,0,0,0
canvas.before:
Color:
rgba: (.47,.47,.47,1) if self.state=='normal' else (.2,1,.6,1)
RoundedRectangle:
pos: self.pos
size: self.size
radius: [8,]
<TabbedContainer#ToggleButton>:
background_color: (1, .5, 0, 1)
background_normal: ''
size_hint_y: None
height: 50
size_hint_x: (1 / 3)
spacing: 30
<Tab>:
canvas.before:
Color:
rgba: (.89, .89, .89, 1)
Rectangle:
size: self.size
pos: self.pos
orientation: 'lr-tb'
BoxLayout:
orientation: 'horizontal'
size_hint_y: None
height: 30
canvas.before:
Color:
rgba: (1, .3, 0, 1)
Rectangle:
size: self.size
pos: self.pos
Label:
text: 'Test'
color: (1, 1, 1, 1)
size_hint_x: 1
StackLayout:
orientation: 'lr-tb'
Label:
text: ''
size_hint_x: 1
size_hint_y: None
height: 10
TabbedContainer:
id: import_tog
text: 'Import'
state: 'down'
group: 'admin_navs'
on_state: root.change_screen(self)
TabbedContainer:
id: calculate_tog
text: 'Calculate'
group: 'admin_navs'
on_state: root.change_screen(self)
TabbedContainer:
id: settings_tog
text: 'Settings'
group: 'admin_navs'
on_state: root.change_screen(self)
BoxLayout:
id: ui_content
padding: 10
ScreenManager: #Problem here I think
id: scrn_man
Screen:
id: import_scrn
name: 'import_scrn'
StackLayout:
orientation: 'lr-tb'
Label:
text: ''
size_hint_x: 1
Label:
text: ''
size_hint_x: 0.2
RoundedButton:
text: 'Choose File'
size_hint_x: 0.2
TextInput:
id: get_file
readonly: True
size_hint_x: 0.5
Label:
text: ''
size_hint_x: 0.1
Label:
text: ''
size_hint_x: 0.2
RoundedButton:
text: 'Import'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.6
StackLayout:
id: import_data_content
orientation: 'lr-tb'
size_hint_y: None
height: 90
Screen:
id: calculate_scrn
name: 'calculate_scrn'
Screen:
id: settings_scrn
name: 'settings_scrn'
StackLayout:
orientation: 'lr-tb'
size_hint_x: 0.5
Label:
text: ''
size_hint_x: 0.1
Button:
text: 'Add Employee'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.2
Button:
text: 'CSV'
size_hint_x: 0.2
Label:
text: ''
size_hint_x: 0.3
BoxLayout:
orientation: 'horizontal'
size_hint_x: 0.5
Label:
text: 'In Time'
size_hint_x: 0.7
TextInput:
size_hint_x: 0.3
Label:
text: 'Out Time'
size_hint_x: 0.7
TextInput:
size_hint_x: 0.3
""")
class TabbedContainer(ToggleButton):
pass
class FileChoosePopup(Popup):
load = ObjectProperty()
class RoundedButton(Button):
pass
class RoundedCancelButton(Button):
pass
class RoundedAcceptButton(Button):
pass
class Tab(StackLayout):
file_path = StringProperty("No file chosen")
the_popup = ObjectProperty(None)
def __init__(self, **kwargs):
super().__init__(**kwargs)
#load import window on initialisation
import_window = self.ids.import_scrn
self.ids.scrn_man.current = 'import_scrn'
def change_screen(self, instance):
if instance.text == 'Import':
self.ids.scrn_man.current = 'import_scrn'
elif instance.text == 'Calculate':
self.ids.scrn_man.current = 'calculate_scrn'
else:
self.ids.scrn_man.current = 'settings_scrn'
class TestApp(App):
def build(self):
return Tab()
if __name__ == '__main__':
TestApp().run()
I expect that the import screen must show on initialisation and screens transition on toggle button state: down. Can someone please give me some advice on how to make my App act as explained above?
Your screens are loading correctly according to your settings. You need to review your entire kv string looking at your size_hint settings. Check each item that contains children and make sure that the total of size_hint_x for its children is less than or equal to 1.0 and the same for size_hint_y.

Using jsonstore in Kivy

I created a GUI based off this question while trying to teach myself how to use jsonstore. I don't have the reputation points to add a comment so I'm asking my question here. I think I have the basic idea down but for some reason I can't save the data to a json file. I get the following error:
AttributeError: 'NoneType' object has no attribute 'text'
I've tried following the documentation but I can't see anywhere where it would explain what I'm doing wrong.
main.py
from kivy.storage.jsonstore import JsonStore
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.core.window import Window
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.properties import BooleanProperty, ListProperty, StringProperty, ObjectProperty
Window.clearcolor = (0.02745098, 0.074509804, 0.121568627, 1)
Window.size = (2000, 900)
class TitleScreen(Screen):
pass
class MainScreen(Screen):
pass
class CreateProfile(Screen):
First = ObjectProperty()
Middle = ObjectProperty()
Last = ObjectProperty()
def __init__(self, **kwargs):
super(CreateProfile, self).__init__(**kwargs)
self.store = JsonStore("bco.json")
self.load()
def save(self):
self.store.put('profile', first = self.label.text)
self.store.put('profile', middle = self.label.text)
self.store.put('profile', last = self.label.text)
def load(self):
try:
self.Last.text = self.store.get('profile')['score']
except KeyError:
pass
class CreatePacket(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("customwidget.kv")
class CustomWidgetApp(App):
def build(self):
return presentation
if __name__ == "__main__":
CustomWidgetApp().run()
customwidget.kv
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import hex kivy.utils.get_color_from_hex
#: import FocusBehaviors kivy.uix.behaviors.focus
ScreenManagement:
transition: FadeTransition()
TitleScreen:
MainScreen:
CreateProfile:
CreatePacket:
<MainLabel#Label>:
font_size:50
bold: True
size_hint_x: 1
size_hint_y: 1.85
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
<SubLabel#Label>:
font_size: 35
bold: True
halign: "center"
size_hint_x: 1
size_hint_y: 1.5
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
<OtherLabel#Label>:
font_size: 12
bold: True
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
text_size: self.size
<Button#Button>:
font_size: 20
bold: True
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
background_color: 0.02745098, 0.074509804, 0.121568627, .01
canvas.before:
Color:
rgba: 0.396078431, 0.803921569, 0.807843137, 1
Line:
width: 2
rectangle: self.x, self.y, self.width, self.height
on_press: self.background_color = (0.396078431, 0.803921569, 0.807843137, 1)
on_release: self.background_color = (0.02745098, 0.074509804, 0.121568627, .01)
# TODO: Create a focus behavior to "Tab" between widgets
<TextInput#TextInput>:
font_size: 12
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
padding_x: 10
padding_y: 10
focus_next: None
focus_previous: None
unfocus_on_touch: True
background_color: 0.02745098, 0.074509804, 0.121568627, .01
canvas.before:
Color:
rgba: 0.396078431, 0.803921569, 0.807843137, 1
Line:
width: 1
rectangle: self.x, self.y, self.width, self.height
<TitleScreen>:
id: "title"
FloatLayout:
MainLabel:
text: "Easy Button"
size_hint_x: 1
size_hint_y: 1.25
SubLabel:
text: 'Test'
size_hint_x: 1
size_hint_y: 1
Button:
text: "Click Here To Continue"
on_release: app.root.current = "main"
size_hint: (.75, .15)
pos_hint: {'x': .12, 'y': .2}
<MainScreen>:
name: "main"
MainLabel:
text: "Home Page"
BoxLayout:
Button:
on_release: app.root.current = "create_profile"
text: "Create Profile"
size_hint: (.5, .15)
Button:
on_release: app.root.current = "create_packet"
text: "Create Packet"
size_hint: (.5, .15)
<CreateProfile>:
name: "create_profile"
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
MainLabel:
text: "Create Profile"
size_hint: (1, .15)
BoxLayout:
size_hint: (.95, .2)
pos_hint: {'x': 0, 'y': .85}
spacing: 10
padding: 10
halign: "left"
OtherLabel:
text: "First"
OtherLabel:
text: "Middle"
OtherLabel:
text: "Last"
BoxLayout:
size_hint: (.95, .07)
pos_hint: {'x': 0, 'y': .8}
spacing: 20
padding: 10
halign: "right"
text_size: self.size
TextInput:
id: 'First'
TextInput:
id: "Middle"
TextInput:
id: 'Last'
BoxLayout:
Button:
on_release: app.root.current = "main"
text: "back Home"
size_hint: (.5, .15)
Button:
on_release: root.save()
text: "Save Profile"
size_hint: (.5, .15)
<CreatePacket>:
name: "create_packet"
MainLabel:
text: "Select Packet"
FloatLayout:
Button:
on_release: app.root.current = "main"
text: "back Home"
size_hint: (1, .15)
Your code has several problems but the main one is that you do not understand how to expose any .kv widget to .py, one of the simplest ways is to use an ObjectProperty as you try to do but that property is not linked to the widget, I prefer to do the creation in the .kv for its simplicity.
On the other hand I recommend you avoid the abuse of try-except since it hides errors, the best thing is to verify.
Another error is that you are overwriting the value of profile in the .json, the idea is to save everything in one.
Considering the above, the solution is:
*.py
from kivy.app import App
from kivy.storage.jsonstore import JsonStore
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.core.window import Window
from kivy.clock import Clock
Window.clearcolor = (0.02745098, 0.074509804, 0.121568627, 1)
Window.size = (2000, 900)
class TitleScreen(Screen):
pass
class MainScreen(Screen):
pass
class CreateProfile(Screen):
def __init__(self, **kwargs):
super(CreateProfile, self).__init__(**kwargs)
self.store = JsonStore("bco.json")
Clock.schedule_once(lambda *args: self.load())
def save(self):
self.store.put('profile',
first = self.first.text,
middle = self.middle.text,
last = self.last.text)
def load(self):
if self.store.exists('profile'):
profile = self.store.get('profile')
v = [("first", self.first), ("middle", self.middle), ("last", self.last)]
for key, ti in v:
val = profile.get(key)
if val:
ti.text = val
class CreatePacket(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("customwidget.kv")
class CustomWidgetApp(App):
def build(self):
return presentation
if __name__ == "__main__":
CustomWidgetApp().run()
*.kv
#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import hex kivy.utils.get_color_from_hex
#: import FocusBehaviors kivy.uix.behaviors.focus
ScreenManagement:
transition: FadeTransition()
TitleScreen:
MainScreen:
CreateProfile:
CreatePacket:
<MainLabel#Label>:
font_size:50
bold: True
size_hint_x: 1
size_hint_y: 1.85
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
<SubLabel#Label>:
font_size: 35
bold: True
halign: "center"
size_hint_x: 1
size_hint_y: 1.5
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
<OtherLabel#Label>:
font_size: 12
bold: True
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
text_size: self.size
<Button#Button>:
font_size: 20
bold: True
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
background_color: 0.02745098, 0.074509804, 0.121568627, .01
canvas.before:
Color:
rgba: 0.396078431, 0.803921569, 0.807843137, 1
Line:
width: 2
rectangle: self.x, self.y, self.width, self.height
on_press: self.background_color = (0.396078431, 0.803921569, 0.807843137, 1)
on_release: self.background_color = (0.02745098, 0.074509804, 0.121568627, .01)
# TODO: Create a focus behavior to "Tab" between widgets
<TextInput#TextInput>:
font_size: 12
color: 0.396078431, 0.803921569, 0.807843137, 1
font_name: '/home/jarren/PycharmProjects/BCO_Form_Filler/practice/pirulen rg.ttf'
padding_x: 10
padding_y: 10
focus_next: None
focus_previous: None
unfocus_on_touch: True
background_color: 0.02745098, 0.074509804, 0.121568627, .01
canvas.before:
Color:
rgba: 0.396078431, 0.803921569, 0.807843137, 1
Line:
width: 1
rectangle: self.x, self.y, self.width, self.height
<TitleScreen>:
id: "title"
FloatLayout:
MainLabel:
text: "Easy Button"
size_hint_x: 1
size_hint_y: 1.25
SubLabel:
text: 'Test'
size_hint_x: 1
size_hint_y: 1
Button:
text: "Click Here To Continue"
on_release: app.root.current = "main"
size_hint: (.75, .15)
pos_hint: {'x': .12, 'y': .2}
<MainScreen>:
name: "main"
MainLabel:
text: "Home Page"
BoxLayout:
Button:
on_release: app.root.current = "create_profile"
text: "Create Profile"
size_hint: (.5, .15)
Button:
on_release: app.root.current = "create_packet"
text: "Create Packet"
size_hint: (.5, .15)
<CreateProfile>:
name: "create_profile"
first: first
middle: middle
last: last
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
MainLabel:
text: "Create Profile"
size_hint: (1, .15)
BoxLayout:
size_hint: (.95, .2)
pos_hint: {'x': 0, 'y': .85}
spacing: 10
padding: 10
halign: "left"
OtherLabel:
text: "First"
OtherLabel:
text: "Middle"
OtherLabel:
text: "Last"
BoxLayout:
size_hint: (.95, .07)
pos_hint: {'x': 0, 'y': .8}
spacing: 20
padding: 10
halign: "right"
text_size: self.size
TextInput:
id: first
TextInput:
id: middle
TextInput:
id: last
BoxLayout:
Button:
on_release: app.root.current = "main"
text: "back Home"
size_hint: (.5, .15)
Button:
on_release: root.save()
text: "Save Profile"
size_hint: (.5, .15)
<CreatePacket>:
name: "create_packet"
MainLabel:
text: "Select Packet"
FloatLayout:
Button:
on_release: app.root.current = "main"
text: "back Home"
size_hint: (1, .15)
I found a work around that still allows me to append information into a JSON by using TinyDB. Here is the updated code:
from kivy.app import App
from kivy.storage.jsonstore import JsonStore
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.core.window import Window
from tinydb import TinyDB, Query
from kivy.uix.listview import ListItemButton
Window.clearcolor = (0.02745098, 0.074509804, 0.121568627, 1)
Window.size = (2000, 900)
db = TinyDB('bcodb.json')
class ProfileListButton(ListItemButton):
pass
class TitleScreen(Screen):
pass
class MainScreen(Screen):
pass
class CreateProfile(Screen):
def __init__(self, **kwargs):
super(CreateProfile, self).__init__(**kwargs)
self.store = JsonStore("bcodb.json")
def save(self):
db.insert({'first': self.first.text, 'middle': self.middle.text, 'last': self.last.text})
def update(self):
db.update({'first': self.first.text, 'middle': self.middle.text, 'last': self.last.text})
class CreatePacket(Screen):
pass
class ScreenManagement(ScreenManager):
pass
presentation = Builder.load_file("customwidget2.kv")
class CustomWidgetApp(App):
def build(self):
return presentation
if __name__ == "__main__":
CustomWidgetApp().run()
It's pretty easy to figure out with a simple database-like program I'm trying to develop. The .kv file is the same.

How to change text of a label in the kivy language with python

I was wondering how I could change the text of a label made inside the Kivy language using Python.
Like how would I have user input from python be made as the text of a label in kivy.
(By the way I have the formatting correct in the actual program but I screwed up pasting it to stackoverflow)
Say if I wanted to make the text of the label in from the code be a random number generated in python how would I go about doing that?
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.graphics import Color, Rectangle
from kivy.properties import ObjectProperty
# Create both screens. Please note the root.manager.current: this is how
# you can control the ScreenManager from kv. Each screen has by default a
# property manager that gives you the instance of the ScreenManager used.
Builder.load_string("""
<ButImage#ButtonBehavior+AsyncImage>
<TutImage#ButtonBehavior+AsyncImage>
<MenuScreen>:
GridLayout:
cols: 4
row_force_default: True
col_default_width: 175
row_default_height: 150
padding: 15
spacing: 15
canvas.before:
BorderImage:
# BorderImage behaves like the CSS BorderImage
border: 10, 10, 10, 10
source: '/Users/clayhigh/Desktop/kivy/aot.png'
pos: self.pos
size: self.size
Button:
text: 'Goto settings'
background_color: 1,0,0,0.5
on_press: root.manager.current = 'settings'
ButImage:
on_press: root.manager.current = 'UBW'
id: but
size_hint: .5, .5
opacity: 1 if self.state == 'normal' else .5
allow_stretch: True
keep_ratio: False
source: 'http://s3.amazonaws.com/rapgenius/1361742626_beautiful-ocean-beautiful-pictures-27115524-1440-900.jpg'
Label:
center: but.center
text: "UBW"
color: 0.78,0.145,0.016,2
ButImage:
id: lh
size_hint: .5, .5
opacity: 1 if self.state == 'normal' else .5
allow_stretch: True
keep_ratio: False
source: 'http://s3.amazonaws.com/rapgenius/1361742626_beautiful-ocean-beautiful-pictures-27115524-1440-900.jpg'
Label:
center: lh.center
text: "LH 2"
color: 0,0,0,1
ButImage:
id: ttl
size_hint: .5, .5
opacity: 1 if self.state == 'normal' else .5
allow_stretch: True
keep_ratio: False
source: 'http://s3.amazonaws.com/rapgenius/1361742626_beautiful-ocean-beautiful-pictures-27115524-1440-900.jpg'
Label:
center: ttl.center
text: "TwTl"
color: 0,0,0,1
ButImage:
id: gris
size_hint: .5, .5
opacity: 1 if self.state == 'normal' else .5
allow_stretch: True
keep_ratio: False
source: 'http://s3.amazonaws.com/rapgenius/1361742626_beautiful-ocean-beautiful-pictures-27115524-1440-900.jpg'
Label:
center: gris.center
text: "Gris"
color: 0,0,0,1
ButImage:
id: shig
size_hint: .5, .5
opacity: 1 if self.state == 'normal' else .5
allow_stretch: True
keep_ratio: False
source: 'http://s3.amazonaws.com/rapgenius/1361742626_beautiful-ocean-beautiful-pictures-27115524-1440-900.jpg'
Label:
center: shig.center
text: "Shig"
color: 0,0,0,1
Button:
text: 'Test3'
background_color: 1,0,0,0.5
Button:
text: 'Test4'
background_color: 1,0,0,0.5
Button:
text: 'Quit'
background_color: 1,0,0,0.5
on_press: App.on_stop
<SettingsScreen>:
GridLayout:
row_force_default: True
row_default_height: 100
cols: 2
canvas.before:
BorderImage:
# BorderImage behaves like the CSS BorderImage
border: 10, 10, 10, 10
source: '/Users/clayhigh/Desktop/kivy/ato.jpeg'
pos: self.pos
size: self.size
Button:
text: 'Button'
color: 0,0,.5
background_color: 1,0,0,1
Button:
text: 'Back to menu'
background_color: 1,0,0,1
on_press: root.manager.current = 'menu'
<UBW>:
GridLayout:
row_force_default: True
row_default_height: 100
cols: 2
canvas.before:
Color:
rgb: .5, .5, .5
Rectangle:
pos: self.pos
size: self.size
Color:
rgb: 1, 1, 1
BorderImage:
# BorderImage behaves like the CSS BorderImage
border: 10, 10, 10, 10
source: '/Users/clayhigh/Desktop/kivy/fsn.jpg'
pos: self.pos
size: self.size
Button:
text: 'Back to menu'
color: 0,0,.5
on_press: root.manager.current = 'menu'
background_color: 1,0,0,1
Label:
id: AName
text: "F S/N: UBW"
font_size: '24sp'
""")
# Declare both screens
class MenuScreen(Screen):
pass
class SettingsScreen(Screen):
pass
class UBW(Screen):
pass
# Create the screen manager
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(SettingsScreen(name='settings'))
sm.add_widget(UBW(name='UBW'))
class TestApp(App):
def build(self):
return sm
if __name__ == '__main__':
TestApp().run()
Text of a label can be a kivy property, which can be later changed and since it is a kivy property it will automatically updated everywhere. Here is an example of your .py
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import StringProperty
import random
class YourWidget(Widget):
random_number = StringProperty()
def __init__(self, **kwargs):
super(YourWidget, self).__init__(**kwargs)
self.random_number = str(random.randint(1, 100))
def change_text(self):
self.random_number = str(random.randint(1, 100))
class YourApp(App):
def build(self):
return YourWidget()
if __name__ == '__main__':
YourApp().run()
and your .kv
<YourWidget>:
BoxLayout:
size: root.size
Button:
id: button1
text: "Change text"
on_release: root.change_text()
Label:
id: label1
text: root.random_number
When you click the button, it will call change_text() function, which will randomly change the text of the label to random integer between 1 and 100.

Categories

Resources