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



我正在尝试编写使用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()

计算器gui.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:UsersWendelinDocumentsProgrammingcalculation>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:UsersWendelin.kivylogskivy_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:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivy__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:UsersWendelinDocumentsProgrammingcalculationvenvScriptspython.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:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 249, in create_handler
return eval(value, idmap), bound_list
File "c:UsersWendelinDocumentsProgrammingcalculationCalculatorcalculatorgui.kv", line 38, in <module>
text: app.angle_mode_text
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangparser.py", line 75, in __getattribute__
object.__getattribute__(self, '_ensure_app')()
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangparser.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:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 692, in _apply_rule  
rctx['ids'])
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 254, in create_handler
cause=tb)
kivy.lang.builder.BuilderException: Parser: File "c:UsersWendelinDocumentsProgrammingcalculationCalculatorcalculatorgui.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:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 249, in create_handler
return eval(value, idmap), bound_list
File "c:UsersWendelinDocumentsProgrammingcalculationCalculatorcalculatorgui.kv", line 38, in <module>
text: app.angle_mode_text
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangparser.py", line 75, in __getattribute__
object.__getattribute__(self, '_ensure_app')()
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangparser.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:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivyuixrelativelayout.py", line 265, in __init__
super(RelativeLayout, self).__init__(**kw)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivyuixfloatlayout.py", line 65, in __init__
super(FloatLayout, self).__init__(**kwargs)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivyuixlayout.py", line 76, in __init__        
super(Layout, self).__init__(**kwargs)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivyuixwidget.py", line 361, in __init__       
rule_children=rule_children)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivyuixwidget.py", line 469, in apply_class_lang_rules
rule_children=rule_children)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 538, in apply        
rule_children=rule_children)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 659, in _apply_rule
child, crule, rootrule, rule_children=rule_children)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 657, in _apply_rule  
root=rctx['ids']['root'], rule_children=rule_children)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivyuixwidget.py", line 469, in apply_class_lang_rules
rule_children=rule_children)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 538, in apply        
rule_children=rule_children)
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 707, in _apply_rule  
e), cause=tb)
kivy.lang.builder.BuilderException: Parser: File "c:UsersWendelinDocumentsProgrammingcalculationCalculatorcalculatorgui.kv", 
line 38:
...
36:        size_hint_x: None
37:        width: "30dp"
>>   38:        text: app.angle_mode_text
39:
40:
...
BuilderException: Parser: File "c:UsersWendelinDocumentsProgrammingcalculationCalculatorcalculatorgui.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:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 249, in create_handler
return eval(value, idmap), bound_list
File "c:UsersWendelinDocumentsProgrammingcalculationCalculatorcalculatorgui.kv", line 38, in <module>
text: app.angle_mode_text
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangparser.py", line 75, in __getattribute__
object.__getattribute__(self, '_ensure_app')()
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangparser.py", line 70, in _ensure_app    
app.bind(on_stop=lambda instance:
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 692, in _apply_rule  
rctx['ids'])
File "c:UsersWendelinDocumentsProgrammingcalculationvenvlibsite-packageskivylangbuilder.py", line 254, in create_handler
cause=tb)

所以似乎我不知何故无法正确访问应用程序实例。 但是,我查看了 Kivy 文档,我正在按规定使用应用程序标识符。

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

问题是加载kv文件时尚未定义App中的Properties。您可以通过将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

最新更新