I have a basic, working knowledge of Python I'm trying to teach myself kivy. I'd like to be able to have Python read and write data to kivy widgets.
Imagine there's an address book app that inserts the date and time into a TextInput. When the app starts, just have Python get the date and time and insert it right?
This program code will give an example of a simple address book:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
class AddressApp(App):
def build(self):
pass
if __name__ == '__main__':
AddressApp().run()
Here's its address.kv file:
GridLayout:
cols: 2
Label:
text: 'Date'
TextInput:
id: textinputdate
Label:
text: 'Time'
TextInput:
id: textinputtime
Label:
text: 'Name'
TextInput:
id: textinputname
Label:
text: 'Address'
TextInput:
id: textinputaddress
Label:
text: 'email'
TextInput:
id: textinputemail
Label:
text: 'Phone'
TextInput:
id: textinputphone
After that, if I wanted to have Python read the... I dunno... uh... phone number TextInput, how would that be done?
If you want some widget to have an extra functionality (example: loading current date at app start), then create a custom version of that widget, which meets requirements. And reading values of widgets within a rule is very simple. Example:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.textinput import TextInput
from kivy.clock import Clock
import time
gui = '''
BoxLayout:
orientation: 'vertical'
GridLayout:
cols: 2
Label:
text: 'current time'
DateInput:
id: date_input
Button:
text: 'write date to console'
on_press: print(date_input.text)
'''
class DateInput(TextInput):
def __init__(self, **kwargs):
super(DateInput, self).__init__(**kwargs)
Clock.schedule_interval(self.update, 1) # update every second
def update(self, dt):
self.text = time.ctime()
class Test(App):
def build(self):
return Builder.load_string(gui)
Test().run()
A guy named spinningD20 on the FreeNode IRC channel for kivy showed me this.
There's an even easier way than adding a custom widget. As long as you just want to insert a value into the TextInput when the app starts up...
address.py
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
import time
class AddressApp(App):
def build(self):
self.root.ids.textinputdate.text = time.strftime("%x")
if __name__ == '__main__':
AddressApp().run()
address.kv
GridLayout:
cols: 2
Label:
text: 'Date'
TextInput:
id: textinputdate
Label:
text: 'Time'
TextInput:
id: textinputtime
Label:
text: 'Name'
TextInput:
id: textinputname
Label:
text: 'Address'
TextInput:
id: textinputaddress
Label:
text: 'email'
TextInput:
id: textinputemail
Label:
text: 'Phone'
TextInput:
id: textinputphone
spinningD20 here. To be fair, I answered his immediate question, but also followed it up with an explanation of encapsulating it into a custom widget:
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
import time
class DateInput(TextInput):
def __init__(self, **kwargs):
super(DateInput, self).__init__(**kwargs)
self.text = time.strftime("%x")
class Container(GridLayout):
def __init__(self, **kwargs):
# using super calls the base class's init. We'll hand it keyword arguments we received, just in case
super(Container, self).__init__(**kwargs)
# now we can do stuff here
self.ids.textinputtime.text = 'from python'
class AddressApp(App):
def build(self):
pass
if __name__ == '__main__':
AddressApp().run()
and in kv:
# anything without the <> symbols is part of the App's kv. So here's the one thing the App will have in its kv
Container:
# here's the custom widget's kv, just like your previous example
<Container>:
cols: 2
Label:
text: 'Date'
DateInput:
id: dateinputdate
Label:
text: 'Time'
TextInput:
id: textinputtime
Label:
text: 'Name'
TextInput:
id: textinputname
Label:
text: 'Address'
TextInput:
id: textinputaddress
Label:
text: 'email'
TextInput:
id: textinputemail
Label:
text: 'Phone'
TextInput:
id: textinputphone
I hope this helped! Good luck Dave!
Another example, explaining how to populate text inputs with current date through a parent grid layout, avoiding App class to keep it clean:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import Clock
from kivy.uix.gridlayout import GridLayout
import time
gui = '''
#:import time time
DateGrid
cols: 1
Label:
text: 'Customer data'
TextInput:
id: date_input
TextInput:
id: name_input
TextInput:
id: email_input
Button:
text: 'refresh date'
on_press: date_input.text = time.ctime()
'''
class DateGrid(GridLayout):
def __init__(self, **kwargs):
super(DateGrid, self).__init__(**kwargs)
Clock.schedule_once(self.populate_inputs, 0.5)
def populate_inputs(self, *x):
_ = self.ids
_.date_input.text = time.ctime()
_.name_input.text = 'Foo Snowman'
_.email_input.text = 'foo.snowman#gravy.com'
class Test(App):
def build(self):
return Builder.load_string(gui)
Test().run()
Related
I am trying to write in a text file after getting an input through TextInput in kivy. The problem is the data gets saved only after i close the app but i want the data to get saved as soon as I leave the specific screen and go to another screen. I am trying to input in add_staff and get it saved in the app through save() function.
import kivymd
import kivy
from kivymd.app import MDApp
from kivy.lang.builder import Builder
from kivy.uix.floatlayout import FloatLayout
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
Builder.load_string('''
<MenuScreen>:
nm:nm_input
BoxLayout:
TextInput:
id:nm_input
Button:
text: 'Add New Staff'
on_press: root.manager.current = 'add_staff'
Button:
text: 'View Staff Profile'
Button:
text: 'Salary report'
<Add_new_staff>:
nam: str(name_input)
job: job_input
GridLayout:
cols: 2
Label:
text: 'Name'
TextInput:
id: name_input
multiline: False
Label:
text: 'Job'
TextInput:
id: job_input
Label:
text: 'Salary'
TextInput:
Label:
text: 'Date of Joining'
TextInput:
Button:
text: 'Back to menu'
on_press: root.manager.current = 'menu'
Button:
text: 'Save'
on_press: root.save(name_input.text, job_input.text);root.manager.current = 'menu'
''')
class MenuScreen(Screen):
pass
class Add_new_staff(Screen):
def save(self, name, job):
fob = open('testi.txt','a')
fob.write(name + "\n")
fob.write(job)
fob.close()
class TestApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(Add_new_staff(name='add_staff'))
return sm
def lo(self,nm):
f=open('log.txt','a')
f.write(nm)
f.close()
if __name__ == '__main__':
TestApp().run()
I'm trying to build an App thats uses certain input Parameters and when hitting a submit button it uses a logic to generate output paramters. I managed to build the app and the input and the triggering via a submit button. Now i want to generate the output, for beginning with an easy logic. I looked up several similar solutions, but somehow they don't work for me.
For some reason my .kv file doen't get the updated value for the label text with the error: "ValueError: Label.text accept only str" Eventough everything is declared as a string in the .py. If i change it in the kv to str("...") I get some code line which i guess is the intern id of the attribute but not the assigned value i want to get.
I hope you can help. Pls don't be too harsh, I#M new to python and kivy...
main .py, shuldn't be part of the problem
Peenomat.py
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.anchorlayout import AnchorLayout
from kivy.core.text import LabelBase
Builder.load_file('Statusbar.kv')
Builder.load_file('Inputparameters.kv')
Builder.load_file('Outputparameters.kv')
#Layout
class Peenomat(AnchorLayout):
pass
class PeenomatApp(App):
def build(self):
return Peenomat()
if __name__=="__main__":
PeenomatApp().run()
.py with the classes and methods for the logic
StatusBar.py
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.properties import ObjectProperty
from kivy.properties import StringProperty
from kivy.app import App
class InputParameters(GridLayout):
verfahren = ObjectProperty(None)
def on_state(self, togglebutton):
tb = togglebutton
if tb.state == 'down':
self.verfahren = tb.text
self.verfahren = tb.text
print(self.verfahren)
return self.verfahren
class StatusBar(BoxLayout):
#InputGrößen
group_mode = False
prozess = ObjectProperty(None)
vorbehandlung = ObjectProperty(None)
material = ObjectProperty(None)
haerte = ObjectProperty(None)
rauheit = ObjectProperty(None)
#OutputGrößen
frequenz = StringProperty(None)
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)
if ip.haerte.value < 50:
self.frequency = str(180)
elif ip.haerte.value < 60:
self.frequency = str(200)
else:
self.frequency = str(220)
#control to see if right value is taken
print(self.frequency, "Hz")
def btn_clear(self):
np = App.get_running_app().root.ids._input_parameters
np.pro1.state = "normal"
np.pro2.state = "normal"
np.pro3.state = "normal"
np.material.text = "Auswahl treffen"
np.haerte.value = 55
np.rauheit.value = 5.5
the .kv file that can't get the label text:
outputparameters.kv
#: import statusbar StatusBar
<OutputParameters#GridLayout>
#Initialisierung .py zu .kv
frequenz: _frequenz
Label:
text:'Frequenz:'
font_size:
Label:
id: _frequenz
text: root.frequenz
font_size: 20
the .kv file with the submit button, shouldn't be part of the problem either, worked perfectly fine before implementing the part ehre i try to update the text
statusbar.kv
#: import statusbar StatusBar
<StatusBar#BoxLayout>
orientation:'horizontal'
Button:
text: 'Clear'
on_press: root.btn_clear()
Button:
text: 'Submit'
on_press: root.btn_submit()
the file where i put in all the inputparameters, rather important:
Inputparameters.kv
#: import statusbar StatusBar
<InputParameters#GridLayout>
#Initialisierung .py zu .kv Ids
prozess: _prozess
pro1: _prozess1
pro2: _prozess2
pro3: _prozess3
vorbehandlung: _vorbehandlung
material: _material
haerte: _haerte
rauheit: _rauheit
#Prozess
Label:
text:'Prozess:
BoxLayout:
orientation: 'horizontal'
id: _prozess
ToggleButton:
id:_prozess1
text:'P-MOH'
group: "proc_group"
on_state: root.on_state(self)
ToggleButton:
id:_prozess2
text:'E-MOH'
group: "proc_group"
on_state: root.on_state(self)
ToggleButton:
id:_prozess3
text:'PE-MOH'
group: "proc_group"
on_state: root.on_state(self)
#Material
Label:
text: 'Material:'
Spinner:
id: _material
text: ""
values:
# Herstellschritte
Label:
text:'Fertigungsschritte:'
Spinner:
id: _vorbehandlung
text:
values:
# Haerte
Label:
text:'Haerte:'
BoxLayout:
orientation: 'vertical'
Label:
text: str(_haerte.value)
Slider:
id: _haerte
# Rauheit
Label:
text:'Rauheit:
BoxLayout:
orientation: 'vertical'
Label:
text:
Slider:
id: _rauheit
and the file where my layout is embedded (also rather necessary)
peenomat.kv
<Peenomat>
AnchorLayout:
anchor_x: 'left'
anchor_y: 'bottom'
GridLayout:
cols: 1
canvas.before:
Color:
Rectangle:
pos: self.pos
size: self.size
InputParameters:
id:_input_parameters
StatusBar:
id:_status_bar
OutputParameters:
id:_output_parameters
I really hope you can help, have been struggeling with this for a while and it should rather be easy...thanks in advance!
In your kv rule for <OutputParameters#GridLayout> you have a line:
frequenz: _frequenz
which sets frequenz to be a reference to the Label with the id of _frequenz. Then in that Label you are setting text using:
text: root.frequenz
So, you are trying to set the text of the Label to a reference to that Label
I suggest trying something like this:
<OutputParameters#GridLayout>
#Initialisierung .py zu .kv
frequenz: _frequenz
frequency: ''
And change the Label to:
Label:
id: _frequenz
text: root.frequency
font_size: 20
But to actually change the value shown in the label, you will need a reference to the instance of OutputParameters, using something like:
App.get_running_app().root.ids._output_parameters.frequency = str(500)
I am trying to retrieve the value of the checkbox on kivy to write some logic. Could someone please help me and tell me where i can find such information in kivy's documentation as i was left with little luck.
here is the code.
Python file:
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel
from kivy.lang import Builder
from kivy.uix.checkbox import CheckBox
from kivy.properties import ObjectProperty
class Tab(TabbedPanel):
check = ObjectProperty(False)
def btn(self):
print(self.check)
class Checkbox(CheckBox):
pass
filekv = Builder.load_file("GUI.kv")
class TabbedPanelApp(App):
def build(self):
return filekv
if __name__ == '__main__':
TabbedPanelApp().run()
Kv file:
<TextInput>:
multiline:False
Tab:
do_default_tab: False
check:checked
TabbedPanelItem:
text: 'Test Request'
GridLayout:
cols:2
spacing: 20
padding: 20
Label:
text: "Sample ID: "
TextInput:
id: id_sample
Checkbox:
#how do i retrieve the value of the checkbox here??
Label:
text: ""
Button:
text: "Submit"
on_press: root.btn()
I tried using:
id: checked
active: checked
value: checked
But nothing worked.
First you have to give an id to the Checkbox:
Checkbox:
id: check_box
... and then you have its state like this:
print(self.ids.check_box.state)
This is a sample program to display "Hello" or "Good-bye" when you push the button 1 or 2, simplified from my real program.
What I want to do is to execute function btn1() and display "Hello" when the program starts, without pushing the button 1.
What lines of code and where should I add?
When I put "Greetings().btn1()" in class Greetings, error: "name Greetings is not defined" occured. Then I put the same command after def build(self) in class GreetingApp, but nothing happened.
In main.py,
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
class Greetings(BoxLayout):
greeting=StringProperty()
def btn1(self):
self.greeting='Hello.'
def btn2(self):
self.greeting='Good-bye.'
class GreetingApp(App):
def build(self):
return Greetings()
GreetingApp().run()
And in greeting.kv,
#: import main main
Greetings:
<Greetings>:
orientation: "vertical"
Label:
text: root.greeting
BoxLayout:
orientation: "horizontal"
Button:
text: '1'
on_press: root.btn1()
Button:
text: '2'
on_press: root.btn2()
Just call btn1 before returning root widget:
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import StringProperty
from kivy.lang import Builder
Builder.load_string('''
<Greetings>:
orientation: "vertical"
Label:
text: root.greeting
BoxLayout:
orientation: "horizontal"
Button:
text: '1'
on_press: root.btn1()
Button:
text: '2'
on_press: root.btn2()
''')
class Greetings(BoxLayout):
greeting = StringProperty()
def btn1(self):
self.greeting = 'Hello.'
def btn2(self):
self.greeting = 'Good-bye.'
class GreetingApp(App):
def build(self):
root = Greetings()
root.btn1()
return root
GreetingApp().run()
The __init__ method runs every time you create an instance of a class.
So what ever you want to do in creation time of the object, you can put in __init__. Initiate the object.
Put this in your Greetings class.
def __init__(self, **kwargs):
super(Greetings, self).__init__(**kwargs)
self.btn1()
Then you call it when you create the object.
Hello I am facing problem when I am using a GUI in python using Kivy. I am using TabbedPanel.
TabbedPanelItem:
text: 'apple'
BoxLayout:
Label:
text: 'Label1'
Entry:
text: 'Entry1'
CheckBox:
text: 'CheckBox1'
Button:
text: 'Button1'
TabbedPanelItem:
text: 'Grape'
BoxLayout:
Label:
text: 'Label1'
Button:
text: 'Button1'
Several things:
you can have only one build method
return in the second build method, is incorrectly indented, should be same as for
you can always only have one App class not class AccordionApp(App): and class KivyGuiApp(App):
Here is a smaller version of your app from which you should be able to implement more from
'''
TabbedPanel
============
Test of the widget TabbedPanel.
'''
from kivy.app import App
from kivy.uix.tabbedpanel import TabbedPanel, TabbedPanelItem
from kivy.lang import Builder
from kivy.uix.checkbox import CheckBox
from kivy.uix.accordion import Accordion, AccordionItem
from kivy.uix.button import Button
from kivy.app import App
Builder.load_string("""
<Test>:
TabbedPanelItem:
text: 'apple'
BoxLayout:
Label:
text: 'Label1'
Label:
text: 'Entry1'
CheckBox:
text: 'CheckBox1'
Button:
text: 'Button1'
""")
class Test(TabbedPanel):
pass
class KivyGuiApp(App):
def build(self):
test = Test()
acc = Accordion()
for x in range(5):
item = AccordionItem(title='Table %d' % x)
item.add_widget(Button(text='apple\n'))
item.add_widget(Button(text='Grape\n'))
item.add_widget(Button(text='Lemon\n'))
acc.add_widget(item)
panel = TabbedPanelItem()
panel.add_widget(acc)
test.add_widget(panel)
return test
if __name__ == '__main__':
KivyGuiApp().run()