So, I've been working on a very simple kivy app and am having trouble with the backend. How would you go about getting the values from text_input and changing label values? I've watched a few tutorials but their methods vary and I get error messages. Here is my python code:
import kivy
from kivy.app import App
kivy.require('1.9.1')
class MyWindowApp(App):
pass
window = MyWindowApp()
window.run()
And here is the .kv file:
Screen:
side: side
FloatLayout:
Label:
text: "Side:"
pos_hint: {"x": 0.1, "y": 0.7}
text_size: self.size
Label:
text: "Volume:"
pos_hint: {"x": 0.1, "y": 0.65}
text_size: self.size
Label:
text: "Surface Area:"
pos_hint: {"x": 0.1, "y": 0.6}
text_size: self.size
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x": 0.24, "y": 0.7}
id: side
Label:
text: "0cm"
id: volume
pos_hint: {"x": 0.27, "y": 0.65}
text_size: self.size
Label:
text: "0cm"
id: surface_area
pos_hint: {"x": 0.355, "y": 0.6}
text_size: self.size
As mentioned in the other answer, place Builder.load_file
or Builder.load_string
in your build
method.
To handle changes e.g. if the user hits enter in the side input use on_text_validate: app.on_side_change(self)
or place a button to trigger the calculation and use on_press
method.
The on_side_change
method in your class MyApp
will handle the change. It will be called once the user hits enter. See the example code below, for a basic calculation.
For getting/setting values from the labels/inputs you can use ObjectProperty
or StringProperty
from kivy.properties
. In the below code I'm using StringProperty
.
Important you need the StringProperty
in your app class and use it in the kv file.
For the mode
of your calculation I've added a property, so you can use it in your calculation method.
The mode
is also used in the kv file so it's displaying the current mode.
The switcher
dictionary is the Python way to do a switch/case statement.
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
kv = """
Screen:
side: side
GridLayout:
rows: 1
cols:2
spacing:0
GridLayout:
rows: 5
cols:1
Button:
text: "Cube"
# on_press: app.mode = self.text
on_press: app.setMode(self)
Button:
text: "Cuboid"
on_press: app.setMode(self)
Button:
text: "Cylinder"
on_press: app.setMode(self)
Button:
text: "Cone"
on_press: app.setMode(self)
Button:
text: "Sphere"
on_press: app.setMode(self)
FloatLayout:
Label:
text: "The Volume and surface area of a {}:".format(app.mode)
pos_hint: {"x":0.1, "y":0.8}
text_size: self.size
Label:
text:"Side:"
pos_hint: {"x":0.1, "y":0.7}
text_size: self.size
Label:
text:"Volume:"
pos_hint: {"x":0.1, "y":0.65}
text_size: self.size
Label:
text:"Surface Area:"
pos_hint: {"x":0.1, "y":0.6}
text_size: self.size
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":0.24, "y":0.7}
id: side
text: app.sideText
on_text_validate: app.on_side_change(self)
Label:
text: app.volume
pos_hint: {"x":0.27, "y":0.65}
text_size: self.size
Label:
text: app.area
pos_hint: {"x":0.355, "y":0.6}
text_size: self.size
"""
class MyApp(App):
sideText = StringProperty("")
area = StringProperty("0 cm²")
volume = StringProperty("0 cm³")
mode = StringProperty("Cube")
def build(self):
return Builder.load_string(kv)
def setMode(self, btn):
self.mode = btn.text
def on_side_change(self, instance):
print(instance.text)
result = 0
try:
value = float(instance.text)
except:
# failed to convert
return
def cubeCalc(val):
return {
"volume": val * val * val,
"area": val * val
}
switcher = {
"Cube": cubeCalc
}
method = switcher.get(self.mode, "Unknown mode")
if method is not "Unknown mode":
result = method(value) # result is a dictionary with volume & area
#print(result)
print(self.volume)
self.volume = "{:.2f} cm³".format(result["volume"])
self.area = "{:.2f} cm²".format(result["area"])
if __name__ == "__main__":
MyApp().run()