Python Kivy AttributeError:“ NoneType”对象没有属性“ bind”

时间:2019-12-19 21:16:52

标签: python python-3.x user-interface kivy kivy-language

我试图用Kivy编写一个计算器GUI。

这是代码:

experiment.py

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import ListProperty, NumericProperty, BooleanProperty, StringProperty
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.lang import Builder 

import calculator_calc




Builder.load_file("calculatorgui.kv")



class CalculatorScreen1(Screen):
    pass

class CalculatorScreen2(Screen):
    pass



class CalculatorModeIndicator(BoxLayout):
    pass

class CalculatorMonitor1(BoxLayout):
    pass

class CalculatorButtons(BoxLayout):
    pass





screen_manager = ScreenManager()

screen_manager.add_widget(CalculatorScreen1(name = "screen1"))
screen_manager.add_widget(CalculatorScreen2(name = "screen2"))



class Calculator(App):
    expression_tokens = ListProperty([])
    expression_value = StringProperty("")
    angle_mode = StringProperty("degrees")
    angle_mode_text = StringProperty("D")
    button_mode = NumericProperty(1)
    button_mode_text = StringProperty("1ST")
    store_mode = BooleanProperty(False)


    def build(self):
        return screen_manager


    def switch_screen(self, screen):
        screen_manager.current = screen

    def set_button_mode(self, button_mode):
        self.button_mode = button_mode

        if button_mode == 1:
            self.button_mode_text = "1ST"
        elif button_mode == 2:
            self.button_mode_text = "2ND"
        elif button_mode == 3:
            self.button_mode_text = "3RD"  

    def set_angle_mode(self, angle_mode):
        calculator_calc.evaluate(f"angle_mode {angle_mode}") 

        self.angle_mode = angle_mode

        if angle_mode == "degrees":
            self.angle_mode_text = "D"
        elif angle_mode == "radians":
            self.angle_mode_text = "R"
        elif angle_mode == "gradians":
            self.angle_mode_text = "G"  

    def add_token(self, token):
        self.expression_tokens.append(token)

    def calculate(self, expression):
        result = calculator_calc.evaluate(expression)
        self.expression_value = str(result)
        calculator_calc.evaluate(f"ANS = {result}")


Calculator().run()

calculatorgui.kv

#:kivy 1.11.1


<CalculatorScreen1>:
    BoxLayout:
        orientation: "vertical"

        CalculatorModeIndicator:

        CalculatorMonitor1:

        CalculatorButtons:


<CalculatorScreen2>:
    BoxLayout:
        orientation: "vertical"

        Label:
            text: "This is Screen 2"

        Button:
            text: "Screen2"
            on_press: app.switch_screen("screen1")


<CalculatorModeIndicator>:
    Label:
        size_hint_x: None
        width: "30dp"
        text: app.button_mode_text

    Label:
        size_hint_x: None
        width: "30dp"
        text: app.angle_mode_text


<CalculatorMonitor1>:    
    orientation: "vertical"

    Label:
        size_hint_y: None
        height: "30dp"
        text_size: self.size
        halign: "left"
        valign: "top"
        text: '"".join(app.expression_tokens)'

    Label:
        size_hint_y: None
        height: "30dp"
        text_size: self.size
        halign: "right"
        valign: "bottom"
        text: 'app.expression_value'


<CalculatorButtons>:    
    orientation: "vertical"

    BoxLayout: 
        Button:
            text: "1ST"
            on_press: app.set_button_mode(1)

        Button:
            text: "2ND"
            on_press: app.set_button_mode(2)

        Button:
            text: "3RD"
            on_press: app.set_button_mode(3)

    BoxLayout:
        Button:
            text: "DEGREES"
            on_press: 
                app.set_angle_mode("degrees")
        Button:
            text: "RADIANS"
            on_press: 
                app.set_angle_mode("radians")
        Button:
            text: "GRADIANS"
            on_press:
                app.set_angle_mode("gradians")

    BoxLayout:
        Button:
            text: "A"
            on_press: app.add_token(self.text) if not app.store_mode else app.store("A")
        Button:
            text: "B"
            on_press: app.add_token(self.text) if not app.store_mode else app.store("B")
        Button:
            text: "C"
            on_press: app.add_token(self.text) if not app.store_mode else app.store("C")
        Button:
            text: "D"
            on_press: app.add_token(self.text) if not app.store_mode else app.store("D")
        Button:
            text: "E"
            on_press: app.add_token(self.text) if not app.store_mode else app.store("E")

    # BoxLayout:
    #     Button:
    #         text: "sin" if app.button_mode == 1 else "asin" if app.button_mode == 2 else "sinh"
    #         on_press: app.add_token(f"{self.text}(")
    #     Button:
    #         text: "cos" if app.button_mode == 1 else "acos" if app.button_mode == 2 else "cosh"
    #         on_press: app.add_token(f"{self.text}(")
    #     Button:
    #         text: "tan" if app.button_mode == 1 else "atan" if app.button_mode == 2 else "tanh"
    #         on_press: app.add_token(f"{self.text}(")
    #     Button:
    #         text: "log"
    #         on_press: app.add_token(self.text + "(")
    #     Button:
    #         text: "ln"
    #         on_press: app.add_token(self.text + "(")

    BoxLayout:
        Button:
            text: "("
            on_press: app.add_token(self.text)
        Button:
            text: ")"
            on_press: app.add_token(self.text)
        Button:
            text: "STO"
            on_press: app.store_mode = True
        Button:
            text: "swt"
            on_press: app.switch_screen("screen2")
        Button:
            text: ","
            on_press: app.add_token(self.text)

    BoxLayout:
        Button:
            text: "7"
            on_press: app.add_token(self.text)
        Button:
            text: "8"
            on_press: app.add_token(self.text)
        Button:
            text: "9"
            on_press: app.add_token(self.text)
        Button:
            text: "DEL"
            on_press: app.expression_tokens = app.expression_tokens[:-1]
        Button:
            text: "AC"
            on_press: 
                app.expression_tokens = []

    BoxLayout:
        Button:
            text: "4"
            on_press: app.add_token(self.text)
        Button:
            text: "5"
            on_press: app.add_token(self.text)
        Button:
            text: "6"
            on_press: app.add_token(self.text)
        Button:
            text: "*"
            on_press: app.add_token(self.text)
        Button:
            text: "/"
            on_press: app.add_token(self.text)

    BoxLayout:
        Button:
            text: "1"
            on_press: app.add_token(self.text)
        Button:
            text: "2"
            on_press: app.add_token(self.text)
        Button:
            text: "3"
            on_press: app.add_token(self.text)
        Button:
            text: "+"
            on_press: app.add_token(self.text)
        Button:
            text: "-"
            on_press: app.add_token(self.text)

    BoxLayout:
        Button:
            text: "0"
            on_press: app.add_token(self.text)
        Button:
            text: "000"
            on_press: app.add_token(self.text)
        Button:
            text: "."
            on_press: app.add_token(self.text)
        Button:
            text: "ANS"
            on_press: app.add_token(self.text)
        Button:
            text: "="
            on_press: app.calculate("".join(app.expression_tokens))

当我尝试运行脚本时,控制台返回以下错误消息:

(venv) C:\Users\Wendelin\Documents\Programming\calculation>c:/Users/Wendelin/Documents/Programming/calculation/venv/Scripts/python.exe c:/Users/Wendelin/Documents/Programming/calculation/Calculator/experiment.py
[INFO   ] [Logger      ] Record log in C:\Users\Wendelin\.kivy\logs\kivy_19-12-19_29.txt
[INFO   ] [deps        ] Successfully imported "kivy_deps.gstreamer" 0.1.17
[INFO   ] [deps        ] Successfully imported "kivy_deps.glew" 0.1.12
[INFO   ] [deps        ] Successfully imported "kivy_deps.sdl2" 0.1.22
[INFO   ] [Kivy        ] v1.11.1
[INFO   ] [Kivy        ] Installed at "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\__init__.py"
[INFO   ] [Python      ] v3.7.5 (tags/v3.7.5:5c02a39a0b, Oct 15 2019, 00:11:34) [MSC v.1916 64 bit (AMD64)]
[INFO   ] [Python      ] Interpreter at "c:\Users\Wendelin\Documents\Programming\calculation\venv\Scripts\python.exe"
[INFO   ] [Factory     ] 184 symbols loaded
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_pil, img_gif (img_ffpyplayer ignored)
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] GLEW initialization succeeded
[INFO   ] [GL          ] Backend used <glew>
[INFO   ] [GL          ] OpenGL version <b'4.4.0 - Build 20.19.15.4463'>
[INFO   ] [GL          ] OpenGL vendor <b'Intel'>
[INFO   ] [GL          ] OpenGL renderer <b'Intel(R) Iris(TM) Graphics 540'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 4
[INFO   ] [GL          ] Shading version <b'4.40 - Build 20.19.15.4463'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <32>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[INFO   ] [Text        ] Provider: sdl2
 Traceback (most recent call last):
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 249, in create_handler
     return eval(value, idmap), bound_list
   File "c:\Users\Wendelin\Documents\Programming\calculation\Calculator\calculatorgui.kv", line 38, in <module>
     text: app.angle_mode_text
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\parser.py", line 75, in __getattribute__
     object.__getattribute__(self, '_ensure_app')()
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\parser.py", line 70, in _ensure_app    
     app.bind(on_stop=lambda instance:
 AttributeError: 'NoneType' object has no attribute 'bind'

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 692, in _apply_rule  
     rctx['ids'])
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 254, in create_handler
     cause=tb)
 kivy.lang.builder.BuilderException: Parser: File "c:\Users\Wendelin\Documents\Programming\calculation\Calculator\calculatorgui.kv", 
line 38:
 ...
      36:        size_hint_x: None
      37:        width: "30dp"
 >>   38:        text: app.angle_mode_text
      39:
      40:
 ...
 AttributeError: 'NoneType' object has no attribute 'bind'
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 249, in create_handler
     return eval(value, idmap), bound_list
   File "c:\Users\Wendelin\Documents\Programming\calculation\Calculator\calculatorgui.kv", line 38, in <module>
     text: app.angle_mode_text
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\parser.py", line 75, in __getattribute__
     object.__getattribute__(self, '_ensure_app')()
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\parser.py", line 70, in _ensure_app    
     app.bind(on_stop=lambda instance:


 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "c:/Users/Wendelin/Documents/Programming/calculation/Calculator/experiment.py", line 39, in <module>
     screen_manager.add_widget(CalculatorScreen1(name = "screen1"))
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\uix\relativelayout.py", line 265, in __init__
     super(RelativeLayout, self).__init__(**kw)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\uix\floatlayout.py", line 65, in __init__
     super(FloatLayout, self).__init__(**kwargs)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\uix\layout.py", line 76, in __init__        
     super(Layout, self).__init__(**kwargs)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\uix\widget.py", line 361, in __init__       
     rule_children=rule_children)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\uix\widget.py", line 469, in apply_class_lang_rules
     rule_children=rule_children)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 538, in apply        
     rule_children=rule_children)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 659, in _apply_rule
     child, crule, rootrule, rule_children=rule_children)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 657, in _apply_rule  
     root=rctx['ids']['root'], rule_children=rule_children)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\uix\widget.py", line 469, in apply_class_lang_rules
     rule_children=rule_children)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 538, in apply        
     rule_children=rule_children)
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 707, in _apply_rule  
     e), cause=tb)
 kivy.lang.builder.BuilderException: Parser: File "c:\Users\Wendelin\Documents\Programming\calculation\Calculator\calculatorgui.kv", 
line 38:
 ...
      36:        size_hint_x: None
      37:        width: "30dp"
 >>   38:        text: app.angle_mode_text
      39:
      40:
 ...
 BuilderException: Parser: File "c:\Users\Wendelin\Documents\Programming\calculation\Calculator\calculatorgui.kv", line 38:
 ...
      36:        size_hint_x: None
      37:        width: "30dp"
 >>   38:        text: app.angle_mode_text
      39:
      40:
 ...
 AttributeError: 'NoneType' object has no attribute 'bind'
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 249, in create_handler
     return eval(value, idmap), bound_list
   File "c:\Users\Wendelin\Documents\Programming\calculation\Calculator\calculatorgui.kv", line 38, in <module>
     text: app.angle_mode_text
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\parser.py", line 75, in __getattribute__
     object.__getattribute__(self, '_ensure_app')()
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\parser.py", line 70, in _ensure_app    
     app.bind(on_stop=lambda instance:

   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 692, in _apply_rule  
     rctx['ids'])
   File "c:\Users\Wendelin\Documents\Programming\calculation\venv\lib\site-packages\kivy\lang\builder.py", line 254, in create_handler
     cause=tb)

因此,似乎我以某种方式无法正确访问该应用程序实例。 但是,我查看了Kivy文档,并按规定使用了应用程序标识符。

我该怎么办?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

问题在于,在加载Properties文件时,尚未定义App中的kv。您可以通过将Builder.load_file()移到App中来更正此错误,这样就已经定义了Properties

screen_manager = ScreenManager()


class Calculator(App):
    expression_tokens = ListProperty([])
    expression_value = StringProperty("")
    angle_mode = StringProperty("degrees")
    angle_mode_text = StringProperty("D")
    button_mode = NumericProperty(1)
    button_mode_text = StringProperty("1ST")
    store_mode = BooleanProperty(False)


    def build(self):
        Builder.load_file("calculatorgui.kv")
        screen_manager.add_widget(CalculatorScreen1(name = "screen1"))
        screen_manager.add_widget(CalculatorScreen2(name = "screen2"))
        return screen_manager