如何在 Kivy/Python 中从一个屏幕引用另一个屏幕的 TextInput?
How to ref a TextInput from one screen in another screen in Kivy/Python?
我正在尝试制作一个可以计算圆锥体体积的应用程序(到目前为止)。
我有一个名为 ConeVolumeScreen 的屏幕,它有两个 TextInput 小部件。
<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')
一个人应该将圆锥体的半径和高度输入到这两个小部件中。然后此人可以单击按钮转到名为 SolveConeVolumeScreen 的下一个屏幕。在此屏幕中有一个标签,该标签应打印人员指定的圆锥体积。
<SolveConeVolumeScreen>:
BoxLayout:
orientation: ...
padding: ...
spacing: ...
Label:
text: app.getConeVolume(cone_vol_radius, cone_vol_height)
getConeVolume() 是这里的一个方法
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
但是错误说cone_vol_radius没有定义。
...
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
请帮忙。如果有任何建议,我将不胜感激。
这是我的屏幕管理员
<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'
错误
应用程序中有几个错误。
NameError - 解决方案
将 root.ids.ids.coneVolume_screen.ids.
添加到参数中。
属性错误
解决NameError后,会出现AttributeError。 AttributeError: 'NoneType' object has no attribute 'ids'
。这是因为内部 ID 尚不可用。
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 - 解决方案
- 给标签一个
id
例如id: result
- 添加一个
on_pre_enter
事件来调用 getConeVolume()
方法。
- 用 TextInput 的文本替换 TextInput 对象,即将
cone_vol_radius
和 cone_vol_height
分别替换为 cone_vol_radius.text
和 cone_vol_height.text
。
- 添加
int()
函数将 TextInput 的 text/string 转换为整数。
片段
<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
输出
我正在尝试制作一个可以计算圆锥体体积的应用程序(到目前为止)。 我有一个名为 ConeVolumeScreen 的屏幕,它有两个 TextInput 小部件。
<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')
一个人应该将圆锥体的半径和高度输入到这两个小部件中。然后此人可以单击按钮转到名为 SolveConeVolumeScreen 的下一个屏幕。在此屏幕中有一个标签,该标签应打印人员指定的圆锥体积。
<SolveConeVolumeScreen>:
BoxLayout:
orientation: ...
padding: ...
spacing: ...
Label:
text: app.getConeVolume(cone_vol_radius, cone_vol_height)
getConeVolume() 是这里的一个方法
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
但是错误说cone_vol_radius没有定义。
...
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
请帮忙。如果有任何建议,我将不胜感激。
这是我的屏幕管理员
<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'
错误
应用程序中有几个错误。
NameError - 解决方案
将 root.ids.ids.coneVolume_screen.ids.
添加到参数中。
属性错误
解决NameError后,会出现AttributeError。 AttributeError: 'NoneType' object has no attribute 'ids'
。这是因为内部 ID 尚不可用。
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 - 解决方案
- 给标签一个
id
例如id: result
- 添加一个
on_pre_enter
事件来调用getConeVolume()
方法。 - 用 TextInput 的文本替换 TextInput 对象,即将
cone_vol_radius
和cone_vol_height
分别替换为cone_vol_radius.text
和cone_vol_height.text
。 - 添加
int()
函数将 TextInput 的 text/string 转换为整数。
片段
<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