问题
I'm trying to make an app that can calculate the volume of a cone(so far). I have a screen named ConeVolumeScreen that has two TextInput widgets.
<ConeVolumeScreen>:
BoxLayout:
orientation: ...
padding: ...
spacing: ...
Label:
text: 'Radius:'
TextInput:
id: cone_vol_radius
multiline: False
input_type: 'number'
Label:
text: 'Height:'
TextInput:
id: cone_vol_height
multiline: False
input_type: 'number'
Button:
text: 'Solve'
on_release: app.root.changeScreen('solve cone volume')
A person is supposed to enter the radius and height of the cone into these two widgets. Then the person can click on a button to go to the next screen named SolveConeVolumeScreen. In this screen there is a Label that should print the volume of the cone that the person specified.
<SolveConeVolumeScreen>:
BoxLayout:
orientation: ...
padding: ...
spacing: ...
Label:
text: app.getConeVolume(cone_vol_radius, cone_vol_height)
getConeVolume() is a method over here
class CalculatorRoot(BoxLayout):
def __init__(self, **kwargs):
super(CalculatorRoot, self).__init__(**kwargs)
self.screen_list = []
def changeScreen(self, next_screen):
if self.ids.calc_screen_manager.current not in self.screen_list:
self.screen_list.append(self.ids.calc_screen_manager.current)
if next_screen == 'volume':
self.ids.calc_screen_manager.current = 'volume_screen'
elif next_screen == 'area_screen':
self.ids.calc_screen_manager.current = 'area_screen'
elif next_screen == 'surface area':
self.ids.calc_screen_manager.current = 'surfarea_screen'
elif next_screen == 'cone volume':
self.ids.calc_screen_manager.current = 'coneVolume_screen'
elif next_screen == 'solve cone volume':
self.ids.calc_screen_manager.current = 'solveConeVolume_screen'
elif next_screen == 'rectangular based pyramid volume':
self.ids.calc_screen_manager.current = 'rectPyramidVolume_screen'
def onBackButton(self):
if self.screen_list:
self.ids.calc_screen_manager.current = self.screen_list.pop()
return True
return False
class CalculatorApp(App):
def __init__(self, **kwargs):
super(CalculatorApp, self).__init__(**kwargs)
Window.bind(on_keyboard=self.onBackButton)
def onBackButton(self, window, key, *args):
if key == 27:
return self.root.onBackButton()
def build(self):
return CalculatorRoot()
def getConeVolume(self, r, h):
first_step = 'π * ' + str(r) + '^2 * ' + str(h) + ' / 3\n'
rr = round(r * r, 2)
second_step = 'π * ' + str(rr) + ' * ' + str(h) + ' / 3\n'
rh = round(rr * h, 2)
third_step = 'π * ' + str(rh) + ' / 3\n'
pirh = round(pi * rh, 2)
fourth_step = str(pirh) + ' / 3\n'
result = round(pi * rh, 2)
final_step = 'The answer is ' + str(result) + '.'
thing = first_step + second_step + third_step + fourth_step + final_step
return thing
But the error says that cone_vol_radius is not defined.
...
128: spacing: min(root.width, root.height) * .02
129: Label:
130: text: app.getConeVolume(cone_vol_radius, cone_vol_height) 131: 132:: ... BuilderException: Parser: File "/Users/fayzulloh/Desktop/Calculator App/calculator.kv", line 130: ... 128: spacing: min(root.width, root.height) * .02 129: Label: 130: text: app.getConeVolume(cone_vol_radius, cone_vol_height) 131: 132:: ... NameError: name 'cone_vol_radius' is not defined
please help. I would really appreciate any advice.
here is my screenmanager
<CalculatorRoot>:
orientation: "vertical"
ScreenManager:
id: calc_screen_manager
StartScreen:
name: 'start_screen'
VolumeScreen:
id: volume_screen
name: 'volume_screen'
AreaScreen:
id: area_screen
name: 'area_screen'
SurfaceAreaScreen:
id: surfarea_screen
name: 'surfarea_screen'
ConeVolumeScreen:
id: coneVolume_screen
name: 'coneVolume_screen'
SolveConeVolumeScreen:
id: solveConeVolume_screen
name: 'solveConeVolume_screen'
RectPyramidVolumeScreen:
id: rectPyramidVolume_screen
name: 'rectPyramidVolume_screen'
回答1:
Errors
There are a couple of errors in the application.
NameError - Solution
Add root.ids.ids.coneVolume_screen.ids.
to the arguments.
AttributeError
After solving the NameError, an AttributeError will occurred. AttributeError: 'NoneType' object has no attribute 'ids'
. This is because inner ids are not available yet.
Kivy Language » ids
Note that the outermost widget applies the kv rules to all its inner widgets before any other rules are applied. This means if an inner widget contains ids, these ids may not be available during the inner widget’s
__init__
function.
AttributeError: ids - Solutions
- Give an
id
to the Label e.g.id: result
- Add an
on_pre_enter
event to invokegetConeVolume()
method. - Replace TextInput object with TextInput's text i.e. replace
cone_vol_radius
andcone_vol_height
withcone_vol_radius.text
andcone_vol_height.text
respectively. - Add
int()
function to convert TextInput's text/string to integer.
Snippet
<SolveConeVolumeScreen>:
on_pre_enter:
root.ids.result.text = app.getConeVolume(int(app.root.ids.coneVolume_screen.ids.cone_vol_radius.text), int(app.root.ids.coneVolume_screen.ids.cone_vol_height.text))
BoxLayout:
orientation: 'vertical'
Label:
id: result
Output
来源:https://stackoverflow.com/questions/52152053/how-to-ref-a-textinput-from-one-screen-in-another-screen-in-kivy-python