【问题标题】:app.root.function unknown in kivy custom widget?kivy 自定义小部件中的 app.root.function 未知?
【发布时间】:2022-11-12 01:32:28
【问题描述】:

我正在尝试学习 Kivy,但我不明白为什么 add_key() 函数可以与 Checkbox 一起使用,但不能与 Spinner 一起使用?

我得到: AttributeError: '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 属性时,复选框工作正常:

拜托,谁能解释一下为什么?谢谢你。

【问题讨论】:

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


    【解决方案1】:

    创建 MainScreen 对象时,尚未设置 app.root 属性。 而且因为您在 MainScreen 构造函数中设置 Spinner 的 text 属性:

    self.ids.pizza_sel.ids.spin_id.text   = pizza[0]
    

    在设置 app.root 之前,您正在调用 Spinner 的 on_text 事件,这就是为什么您最终会出现异常。在这个阶段 app.root 仍然设置为 None。

    不要在构造函数中设置 spin_id.text,而不是在 KV 定义中设置它。

    #self.ids.pizza_sel.ids.spin_id.text   = pizza[0]
    
    Spinner:
        id: spin_id
        text: "margarita"
    

    您还可以将披萨列表添加为 MyApp 类属性:

    class MyApp(App):
        def __init__(self):
            super(MyApp, self).__init__()
            self.pizza = pizza
    

    那么您将能够在 KV 定义中设置 Spinner 文本和值,如下所示:

    Spinner:
        id: spin_id
        text: app.pizza[0]
        values: app.pizza
    

    这样您就可以完全删除 MainScreen 构造函数:

    class MainScreen(Screen):
        # def __init__(self, **kwargs):
        #     super(MainScreen, self).__init__(**kwargs)
        #     self.ids.pizza_sel.ids.spin_id.values = pizza
        #     self.ids.pizza_sel.ids.spin_id.text   = pizza[0]
    

    【讨论】:

      猜你喜欢
      • 2014-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多