Skip to content
Advertisement

Kivy: AttributeError: ‘…’ object has no attribute ‘…’, but it has

I have this TaskTemplate with some Buttons, TexInput, etc. I will put just a piece of code for an easy understanding.

class TaskTemplate(BoxLayout, Button):
    task_name = StringProperty()
    def __init__(self):
        super(TaskTemplate, self).__init__()
        self.update_state = 'down'
<TaskTemplate>:
    RelativeLayout:
        CheckBox:
            state: root.update_state

If I use TaskTemplate as root class it works, I can change the state of the CheckBox with that parameter.
If I add TaskTemplate here:

MainScreen:
<MainScreen>:
    BoxLayout:
        ScrollView:
            GridLayout:
                id: here_add_task_template

I get this error which has no end:

Traceback (most recent call last):
   File "C:UsersbarbuOneDriveDesktopFinal App 2venvlibsite-packageskivylangbuilder.py", line 240, in create_handler
     return eval(value, idmap), bound_list
   File "C:UsersbarbuOneDriveDesktopFinal App 2middleScreen.kv", line 122, in <module>
     state: root.update_state
   File "kivyweakproxy.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:UsersbarbuOneDriveDesktopFinal App 2venvlibsite-packageskivylangbuilder.py", line 694, in _apply_rule
     value, bound = create_handler(
   File "C:UsersbarbuOneDriveDesktopFinal App 2venvlibsite-packageskivylangbuilder.py", line 243, in create_handler
     raise BuilderException(rule.ctx, rule.line,
 kivy.lang.builder.BuilderException: Parser: File "C:UsersbarbuOneDriveDesktopFinal App 2middleScreen.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:UsersbarbuOneDriveDesktopFinal App 2venvlibsite-packageskivylangbuilder.py", line 240, in create_handler
     return eval(value, idmap), bound_list
   File "C:UsersbarbuOneDriveDesktopFinal App 2middleScreen.kv", line 122, in <module>
     state: root.update_state
   File "kivyweakproxy.pyx", line 32, in kivy.weakproxy.WeakProxy.__getattr__
 
 
 During handling of the above exception, another exception occurred:
 
 Traceback (most recent call last):
   File "C:UsersbarbuOneDriveDesktopFinal App 2main.py", line 246, in <module>
     MainApp().run()
   File "C:UsersbarbuOneDriveDesktopFinal App 2venvlibsite-packageskivyapp.py", line 955, in run
     runTouchApp()
   File "C:UsersbarbuOneDriveDesktopFinal App 2venvlibsite-packageskivybase.py", line 574, in runTouchApp
     EventLoop.mainloop()
   File "C:UsersbarbuOneDriveDesktopFinal App 2venvlibsite-packageskivybase.py", line 341, in mainloop
     self.window.mainloop()
   File "C:UsersbarbuOneDriveDesktopFinal App 2venvlibsite-packageskivycorewindowwindow_sdl2.py", line 757, in mainloop
     if self.dispatch('on_key_down', key,
   File "kivy_event.pyx", line 727, in kivy._event.EventDispatcher.dispatch

Advertisement

Answer

Your update_state is just an instance variable of TaskTemplate. So using state: root.update_state in your kv just sets the initial state of the CheckBox. Changing that variable will have no effect on the CheckBox. If you want the CheckBox to reflect changes to the value of update_state, then you have two choices.

  1. Write python code that will update the CheckBox whenever you change the value of update_state.
  2. Change update_state to a Property. Then kv will add the binding to update the CheckBox whenever update_state is changed.

In order to implement #2 above simply change:

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

to:

class TaskTemplate(BoxLayout, Button):
    update_state = StringProperty('down')
    task_name = StringProperty()

Note: unless you have something more planned for TaskTemplate, there is no need for it to extend Button.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement