You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy嵌套TaskTemplate时报AttributeError属性不存在错误

问题描述

我定义了包含Button、TextInput等控件的TaskTemplate组件,核心代码片段如下:

class TaskTemplate(BoxLayout, Button):
    task_name = StringProperty()
    def __init__(self):
        super(TaskTemplate, self).__init__()
        self.update_state = 'down'

对应的kv规则:

<TaskTemplate>:
    RelativeLayout:
        CheckBox:
            state: root.update_state
  • 当TaskTemplate作为应用根类使用时,程序运行完全正常,可以通过update_state参数修改CheckBox的选中状态。
  • 但将TaskTemplate按如下结构添加到MainScreen中时,程序抛出无限循环报错:
MainScreen:
<MainScreen>:
    BoxLayout:
        ScrollView:
            GridLayout:
                id: here_add_task_template

报错核心信息为AttributeError: 'TaskTemplate' object has no attribute 'update_state',完整报错栈如下:

Traceback (most recent call last):
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\venv\lib\site-packages\kivy\lang\builder.py", line 240, in create_handler
     return eval(value, idmap), bound_list
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\middleScreen.kv", line 122, in <module>
     state: root.update_state
   File "kivy\weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
 AttributeError: 'TaskTemplate' object has no attribute 'update_state'
 
 During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\venv\lib\site-packages\kivy\lang\builder.py", line 694, in _apply_rule
     value, bound = create_handler(
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\venv\lib\site-packages\kivy\lang\builder.py", line 243, in create_handler
     raise BuilderException(rule.ctx, rule.line,
 kivy.lang.builder.BuilderException: Parser: File "C:\Users\barbu\OneDrive\Desktop\Final App 2\middleScreen.kv", line 122:
 ...
     120:#                root.update_index()
     121:#                root.save_in_json(self)
 >>  122:            state: root.update_state
     123:
     124:        Button:
 ...
 AttributeError: 'TaskTemplate' object has no attribute 'update_state'
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\venv\lib\site-packages\kivy\lang\builder.py", line 240, in create_handler
     return eval(value, idmap), bound_list
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\middleScreen.kv", line 122, in <module>
     state: root.update_state
   File "kivy\weakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
 
 
 During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\main.py", line 246, in <module>
     MainApp().run()
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\venv\lib\site-packages\kivy\app.py", line 955, in run
     runTouchApp()
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\venv\lib\site-packages\kivy\base.py", line 574, in runTouchApp
     EventLoop.mainloop()
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\venv\lib\site-packages\kivy\base.py", line 341, in mainloop
     self.window.mainloop()
   File "C:\Users\barbu\OneDrive\Desktop\Final App 2\venv\lib\site-packages\kivy\core\window\window_sdl2.py", line 757, in mainloop
     if self.dispatch('on_key_down', key,
   File "kivy\_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch
问题原因

报错由两个核心问题触发:

  1. 继承顺序错误:Kivy控件多继承时,事件交互类需要放在布局类前面,否则会打乱MRO初始化顺序,导致属性、事件注册异常。你写的class TaskTemplate(BoxLayout, Button)顺序完全写反。
  2. 属性定义方式错误:update_state是你在__init__里动态绑定的普通实例属性,不是Kivy原生的Property类型。组件作为根节点时,kv规则解析时机刚好在__init__执行完成后,所以能找到属性;但组件作为子组件嵌套加载时,kv规则解析会发生在__init__属性赋值之前,就会触发属性找不到的错误,再叠加Kivy的规则自动重试机制,就会出现无限循环抛错的现象。
修复方法

按如下步骤修改即可解决问题:

  • 调整类继承顺序,把交互控件类Button放在布局类BoxLayout前面
  • 把update_state定义为类级别的StringProperty(CheckBox的state接受字符串值,对应'normal'/'down'两个状态),直接给默认值,不要在__init__里动态赋值普通属性
  • 给__init__方法添加**kwargs参数,调用父类初始化时把参数透传,避免Kivy控件初始化时丢失必要参数

修改后的Python代码参考:

from kivy.properties import StringProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button

class TaskTemplate(Button, BoxLayout):
    task_name = StringProperty()
    update_state = StringProperty('down')
    def __init__(self, **kwargs):
        super(TaskTemplate, self).__init__(**kwargs)

修改后组件无论作为根节点,还是动态添加到MainScreen的GridLayout中,都能正常加载运行,不会再抛出属性不存在的错误。


内容的提问来源于stack exchange,提问作者Adrian Barbu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 13:27:34