我正在学习Kivy,但我不明白为什么add_key()函数可以和Checkbox一起使用,而不能和Spinner一起使用?
我得到:属性错误:'NoneType'对象没有属性'add_key'?
两个自定义小部件的结构看起来是一样的,add_key函数必须存储在“MainWidget”中。奇怪的是,它可以和复选框一起工作,但不能和微调器一起工作?!
对应于我的问题的最小代码:
from kivy.app import App
from kivy.uix.screenmanager import Screen
from kivy.lang import Builder
selection = {}
pizza = ["margarita", "vegetarian", "american", "3 cheeses"]
KV="""
<Selection@BoxLayout>:
orientation: "horizontal"
label_txt: ""
key_name: ""
Label:
text: root.label_txt
Spinner:
id: spin_id
text: ""
on_text: app.root.add_key(root.key_name, self.text)
<Radio_op@BoxLayout>:
orientation: "horizontal"
op: ""
label_op: ""
Label:
text: root.label_op
CheckBox:
group:"topping"
on_active: app.root.add_key("topping", root.op)
<MainScreen>:
BoxLayout:
orientation: "vertical"
Selection:
id: pizza_sel
label_txt: "pizza"
key_name: "pizza"
Label:
text: "Choose topping:"
BoxLayout:
orientation: "horizontal"
Radio_op:
label_op:"cream"
op: "cream"
Radio_op:
label_op:"cheese"
op: "cheese"
Radio_op:
label_op:"tomatoes"
op: "tomatoes"
BoxLayout:
Label:
id: pizza_lbl
Label:
id: topping_lbl
"""
class MainScreen(Screen):
def __init__(self, **kwargs):
super(MainScreen, self).__init__(**kwargs)
self.ids.pizza_sel.ids.spin_id.text = pizza[0]
self.ids.pizza_sel.ids.spin_id.values = pizza
def add_key(self, name, text):
selection[name] = text
#self.ids.pizza_lbl.text = selection["pizza"]
self.ids.topping_lbl.text = selection["topping"]
Builder.load_string(KV)
class MyApp(App):
def build(self):
return MainScreen()
if __name__ == '__main__':
MyApp().run()`
错误代码:
File "c:\Users\florian\Desktop\Local\Scripts python\Utilitaire de puissance V3\help.py", line 76, in <module>
MyApp().run()
File "C:\Users\florian\Anaconda3\lib\site-packages\kivy\app.py", line 954, in run
self._run_prepare()
File "C:\Users\florian\Anaconda3\lib\site-packages\kivy\app.py", line 924, in _run_prepare
root = self.build()
File "c:\Users\florian\Desktop\Local\Scripts python\Utilitaire de puissance V3\help.py", line 73, in build
return MainScreen()
File "c:\Users\florian\Desktop\Local\Scripts python\Utilitaire de puissance V3\help.py", line 61, in __init__
self.ids.pizza_sel.ids.spin_id.text = pizza[0]
File "kivy\weakproxy.pyx", line 35, in kivy.weakproxy.WeakProxy.__setattr__
File "kivy\properties.pyx", line 520, in kivy.properties.Property.__set__
File "kivy\properties.pyx", line 567, in kivy.properties.Property.set
File "kivy\properties.pyx", line 606, in kivy.properties.Property._dispatch
File "kivy\_event.pyx", line 1307, in kivy._event.EventObservers.dispatch
File "kivy\_event.pyx", line 1189, in kivy._event.EventObservers._dispatch
File "C:\Users\florian\Anaconda3\lib\site-packages\kivy\lang\builder.py", line 55, in custom_callback
exec(__kvlang__.co_value, idmap)
File "<string>", line 11, in <module>
AttributeError: 'NoneType' object has no attribute 'add_key'
当我注解Spinner on_text属性时,复选框工作正常:
拜托,谁能解释一下为什么?谢谢。
2条答案
按热度按时间whlutmcx1#
创建MainScreen对象时,尚未设置app.root属性。并且由于您正在MainScreen构造函数中设置Spinner的text属性:
在设置app.root之前调用Spinner的on_text事件,这就是为什么会出现异常。在这个阶段,app.root仍然设置为None。
不要在构造函数中设置spin_id.text,而要在KV定义中设置它。
您还可以将比萨饼列表添加为MyApp类属性:
然后,您将能够在KV定义中设置微调器文本和值,如下所示:
这样你就可以完全删除MainScreen构造函数:
cwdobuhd2#
谢谢你的回答。
但是使用自定义小部件的要点是使用与其他列表相同的微调器。如果我想用比如说汉堡列表来替换比萨饼列表呢?[鸡肉,美国,素食...]。我的目标是有一个KV文件:
这是一个最简单的例子。但是想象一下,如果我有一长串的食物(薯条、饮料等),我想避免复制/粘贴完整的自定义小部件?控制“选择”只有3个参数?(标签_txt,值),初始微调器。文本总是值[0]?