So im trying to get a variable added to screen and the id fro that is in a widget Im going to add, so if for example I have this:
from kivy.app import App
from kivy.lang import Builder
from kivy.properties import StringProperty
kv = """
Screen:
cal:cal
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
FloatLayout:
id:cal
Label:
text:"Side:"
pos_hint: {"x":1.1, "y":0.7}
text_size: self.size
Label:
text:"Volume:"
pos_hint: {"x":1.1, "y":0.65}
text_size: self.size
Label:
text:"Surface Area:"
pos_hint: {"x":1.1, "y":0.6}
text_size: self.size
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":1.24, "y":0.7}
id: side
text: app.sideText
on_text_validate: app.Cube_on_side_change(self)
Label:
text: app.volume
pos_hint: {"x":1.27, "y":0.65}
text_size: self.size
Label:
text: app.surface_area
pos_hint: {"x":1.355, "y":0.6}
text_size: self.size
"""
cube = """
FloatLayout:
Label:
text:"Side:"
pos_hint: {"x":1.1, "y":0.7}
text_size: self.size
Label:
text:"Volume:"
pos_hint: {"x":1.1, "y":0.65}
text_size: self.size
Label:
text:"Surface Area:"
pos_hint: {"x":1.1, "y":0.6}
text_size: self.size
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":1.24, "y":0.7}
id: side
text: app.sideText
on_text_validate: app.Cube_on_side_change(self)
Label:
text: app.volume
pos_hint: {"x":1.27, "y":0.65}
text_size: self.size
Label:
text: app.surface_area
pos_hint: {"x":1.355, "y":0.6}
text_size: self.size"""
cuboid = """
FloatLayout:
id:main
Label:
text:"Length:"
pos_hint: {"x":1.1, "y":0.7}
text_size: self.size
Label:
text:"Breadth:"
pos_hint: {"x":1.1, "y":0.65}
text_size: self.size
Label:
text:"Height:"
pos_hint: {"x":1.1, "y":0.6}
text_size: self.size
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":1.24, "y":0.7}
id: length
text: app.sideText
on_text_validate: app.Cuboid_on_side_change(self)
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":1.24, "y":0.65}
id: breadth
text: app.sideText
on_text_validate: app.Cube_on_side_change(self)
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":1.24, "y":0.6}
id: height
text: app.sideText
on_text_validate: app.Cuboid_on_side_change()
Label:
text: "Volume:"
pos_hint: {"x":1.1, "y":0.55}
text_size: self.size
Label:
text: "Surface Area:"
pos_hint: {"x":1.1, "y":0.5}
text_size: self.size
Label:
text: app.volume
pos_hint: {"x":1.27, "y":0.55}
text_size: self.size
Label:
text: app.surface_area
pos_hint: {"x":1.355, "y":0.5}
text_size: self.size"""
cone = """
FloatLayout:
Label:
text:"Radius:"
pos_hint: {"x":1.1, "y":0.7}
text_size: self.size
Label:
text:"Height:"
pos_hint: {"x":1.1, "y":0.65}
text_size: self.size
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":1.24, "y":0.7}
id: Radius
text: app.sideText
on_text_validate: app.Cuboid_on_side_change(self)
TextInput:
size_hint: (.4, None)
height: 26
multiline: False
pos_hint: {"x":1.24, "y":0.65}
id: height
text: app.sideText
on_text_validate: app.Cube_on_side_change(self)
Label:
text: "Volume:"
pos_hint: {"x":1.1, "y":0.6}
text_size: self.size
Label:
text: "Surface Area:"
pos_hint: {"x":1.1, "y":0.55}
text_size: self.size
Label:
text: app.volume
pos_hint: {"x":1.27, "y":0.6}
text_size: self.size
Label:
text: app.surface_area
pos_hint: {"x":1.355, "y":0.55}
text_size: self.size
"""
screens = {
"Cube": cube,
"Cuboid": cuboid,
"Cone": cone
}
class MyApp(App):
sideText = StringProperty("")
surface_area = StringProperty("0 cm²")
volume = StringProperty("0 cm³")
mode = StringProperty("Cube")
def build(self):
self.screen = Builder.load_string(kv)
return self.screen
def setMode(self, btn):
self.volume = "0 cm³"
self.surface_area = "0 cm³"
self.mode = btn.text
self.screen.cal.clear_widgets()
self.screen.cal.add_widget(Builder.load_string(screens[self.mode]))
def Cube_on_side_change(self, instance):
try:
value = float(instance.text)
num = True
except ValueError:
# failed to convert
num = False
print("Numbers only idiot.")
def cubeCalc(val):
return {
"volume": val * val * val,
"surface_area": (val * val) * 6
}
if num:
result = cubeCalc(value)
self.volume = "{:.2f} cm³".format(result["volume"])
self.surface_area = "{:.2f} cm²".format(result["surface_area"])
def Cuboid_on_side_change(self):
height = self.screen.cal.ids.main.height.text
try:
value = float(height)
num = True
except ValueError:
# failed to convert
num = False
print("Numbers only idiot.")
def cubeCalc(val):
return {
"volume": val * val * val,
"surface_area": (val * val) * 6
}
if num:
result = cubeCalc(value)
self.volume = "{:.2f} cm³".format(result["volume"])
self.surface_area = "{:.2f} cm²".format(result["surface_area"])
if __name__ == "__main__":
MyApp().run()
on_text_validate
of the TextInput
with id:height
in the string cuboid, I want to get the text from the text input with something like: self.screen.main.height.text
, however, to do that I would have to add main:main
and height:height
to Screen
. How would I do this?
I suggest refactoring your code. Rather than re-inventing the capabilities of ScreenManager
, just use ScreenManager
. In your kv
string, replace the FloatLayout
with:
ScreenManager:
CubeScreen:
CuboidScreen:
ConeScreen:
and use your additional kv
strings (like cube
) as the basis for additional rules in your kv
string. Something like:
<CubeScreen>:
Label:
text: "The Volume and surface area of a Cube:"
pos_hint: {"x":0.1, "y":0.8}
text_size: self.size
FloatLayout:
Label:
text:"Side:"
pos_hint: {"x":0.1, "y":0.7}
text_size: self.size
.
.
.
And define each Screen
class in your py
, like:
class CubeScreen(Screen):
def get_cube_area(self):
.
.
.
And in each of the new classes (like CubeScreen
) you can define methods for calculating area, volume, etc, and you can access the TextInputs
easily using their ids
. And your on_text_validate
in each Screen
can just call the appropriate method from that Screen
(like on_text_validate: root.get_cube_area()
).