如何在 Kivy/Python 的另一个屏幕中从一个屏幕引用 TextInput?

2022-01-15 00:00:00 python kivy nameerror

问题描述

我正在尝试制作一个可以计算圆锥体积的应用程序(到目前为止).我有一个名为 ConeVolumeScreen 的屏幕,它有两个 TextInput 小部件.

<ConeVolumeScreen>:盒子布局:方向: ...填充:...间距:...标签:文本:'半径:'文本输入:编号:cone_vol_radius多行:假输入类型:数字"标签:文字:'身高:'文本输入:编号:cone_vol_height多行:假输入类型:数字"按钮:文字:'解决'on_release: app.root.changeScreen('求解锥体体积')

一个人应该在这两个小部件中输入圆锥的半径和高度.然后该人可以单击一个按钮以转到名为 SolveConeVolumeScreen 的下一个屏幕.在此屏幕中,有一个标签应该打印人员指定的锥体的体积.

<SolveConeVolumeScreen>:盒子布局:方向: ...填充:...间距:...标签:文本:app.getConeVolume(cone_vol_radius, cone_vol_height)

getConeVolume() 是这里的一个方法

类 CalculatorRoot(BoxLayout):def __init__(self, **kwargs):super(CalculatorRoot, self).__init__(**kwargs)self.screen_list = []def changeScreen(self, next_screen):如果 self.ids.calc_screen_manager.current 不在 self.screen_list 中:self.screen_list.append(self.ids.calc_screen_manager.current)如果 next_screen == '音量':self.ids.calc_screen_manager.current = 'volume_screen'elif next_screen == 'area_screen':self.ids.calc_screen_manager.current = 'area_screen'elif next_screen == '表面积':self.ids.calc_screen_manager.current = 'surfarea_screen'elif next_screen == '圆锥体积':self.ids.calc_screen_manager.current = 'coneVolume_screen'elif next_screen == '求解锥体体积':self.ids.calc_screen_manager.current = 'solveConeVolume_screen'elif next_screen == '基于矩形的金字塔体积':self.ids.calc_screen_manager.current = 'rectPyramidVolume_screen'def onBackButton(self):如果 self.screen_list:self.ids.calc_screen_manager.current = self.screen_list.pop()返回真返回假类计算器应用程序(应用程序):def __init__(self, **kwargs):super(CalculatorApp, self).__init__(**kwargs)Window.bind(on_keyboard=self.onBackButton)def onBackButton(self, window, key, *args):如果键 == 27:返回 self.root.onBackButton()定义构建(自我):返回计算器根()def getConeVolume(self, r, h):first_step = 'π * ' + str(r) + '^2 * ' + str(h) + '/3
'rr = 圆形(r * r, 2)second_step = 'π * ' + str(rr) + ' * ' + str(h) + '/3
'rh = 圆形(rr * h, 2)第三步 = 'π * ' + str(rh) + '/3
'pirh = round(pi * rh, 2)第四步 = str(pirh) + '/3
'结果=圆形(pi * rh,2)final_step = '答案是' + str(result) + '.'事情 = first_step + second_step + third_step + Fourth_step + final_step退货

但是错误说没有定义cone_vol_radius.

<代码> ...128: 间距: min(root.width, root.height) * .02129:标签:

<块引用><块引用>

130:文本:app.getConeVolume(cone_vol_radius, cone_vol_height)131:132::...BuilderException:解析器:文件/Users/fayzulloh/Desktop/Calculator App/calculator.kv",第 130 行:...128: 间距: min(root.width, root.height) * .02129:标签:130:文本:app.getConeVolume(cone_vol_radius,cone_vol_height)131:132::...NameError: name 'cone_vol_radius' 未定义

请帮忙.我真的很感激任何建议.

这是我的屏幕管理器

<CalculatorRoot>:方向:垂直"屏幕管理器:id: calc_screen_manager开始屏幕:名称:'start_screen'卷屏:id:volume_screen名称:'volume_screen'区域屏幕:id: area_screen名称:'area_screen'表面积屏幕:id: surfarea_screen名称:surfarea_screen"锥体屏幕:id:coneVolume_screen名称:'coneVolume_screen'SolveConeVolumeScreen:id:solveConeVolume_screen名称:'solveConeVolume_screen'RectPyramidVolumeScreen:id: rectPyramidVolume_screen名称:'rectPyramidVolume_screen'

解决方案

错误

应用程序中有几个错误.

NameError - 解决方案

root.ids.ids.coneVolume_screen.ids. 添加到参数中.

属性错误

解决 NameError 后,会发生 AttributeError.AttributeError: 'NoneType' 对象没有属性 'ids'.这是因为内部 id 尚不可用.

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
'
        rr = round(r * r, 2)
        second_step = 'π * ' + str(rr) + ' * ' + str(h) + ' / 3
'
        rh = round(rr * h, 2)
        third_step = 'π * ' + str(rh) + ' / 3
'
        pirh = round(pi * rh, 2)
        fourth_step = str(pirh) + ' / 3
'
        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'

解决方案

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

  1. Give an id to the Label e.g. id: result
  2. Add an on_pre_enter event to invoke getConeVolume() method.
  3. Replace TextInput object with TextInput's text i.e. replace cone_vol_radius and cone_vol_height with cone_vol_radius.text and cone_vol_height.text respectively.
  4. 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

相关文章