hk22
hk22

Reputation: 49

How to correctly link button by ids in Kivy?

I want to add buttons to boxlayout, but there is some issues in my code. When i click the add button or remove button i receive AttributeError message. Thanks for helping me.

My python code:

from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.screenmanager import Screen, ScreenManager


class MainScreen(Screen):
    pass

class SecondScreen(Screen):
    pass

class ScreenManagement(ScreenManager):
    pass


class TestApp(App):
    def build(self):
        self.title = 'Hello'

    def add_more(self):
        print('test')
        addbutton = self.root.ids.abc
        addbutton.add_widget(Button(text='hello'))

    def remove(self):
        print('test')
        if len(self.root.ids.abc.children) > 0:
            self.root.ids.abc.remove_widget(self.root.ids.abc.children[0])



if __name__=='__main__':
    TestApp().run()

My kv code:

#: import SwapTransition kivy.uix.screenmanager.SwapTransition

ScreenManagement:
    transition: SwapTransition()
    MainScreen:
    SecondScreen:



<MainScreen>:
    BoxLayout:
        id:aaa
        Button:
            text: 'Add'
            on_press: app.add_more()

        Button:
            text:'Remove'
            on_press: app.remove()
        BoxLayout:
            id:abc


<SecondScreen>:

AttributeError: 'super' object has no attribute 'getattr'

Upvotes: 2

Views: 766

Answers (1)

ikolim
ikolim

Reputation: 16041

Problem - AttributeError

     addbutton = self.root.ids.abc
   File "kivy/properties.pyx", line 843, in kivy.properties.ObservableDict.__getattr__
 AttributeError: 'super' object has no attribute '__getattr__'

Root Cause

There is no id: abc in the root which is a ScreenManager.

Solution

There are two options to the solution.

Option 1 - using get_screen()

In this option, we retrieve the instantiated object, MainScreen: using get_screen() function so that we can access its method(s) or attributes e.g. id: abc. We will make the following enhancements:

kv file:

  • We name the screens, name: 'MainScreen' and name: 'SecondScreen' for instantiated objects, MainScreen: and SecondScreen: respectively.

Snippets - kv file

ScreenManagement:
    transition: SwapTransition()
    MainScreen:
        name: 'MainScreen'
    SecondScreen:
        name: 'SecondScreen'

Py file

  • Retrieve the instantiated object, MainScreen using get_screen() function

Snippets - Py file

def add_more(self):
    print('test')
    addbutton = self.root.get_screen('MainScreen').ids.abc
    addbutton.add_widget(Button(text='hello'))

def remove(self):
    print('test')
    container = self.root.get_screen('MainScreen').ids.abc
    if len(container.children) > 0:
        container.remove_widget(container.children[0])

Option 2 - using id: mainscreen

In this option, we add id: mainscreen to instantiated object, MainScreen: and use ids.mainscreen to access its method(s) or attributes e.g. id: abc. We will make the following enhancements:

kv file:

  • Add id: mainscreen to instantiated object, MainScreen:

Snippets - kv file

ScreenManagement:
    transition: SwapTransition()
    MainScreen:
        id: mainscreen
    SecondScreen:

Py file

  • Replace self.root.ids.abc with self.root.ids.mainscreen.ids.abc

Snippets - Py file

def add_more(self):
    print('test')
    addbutton = self.root.ids.mainscreen.ids.abc
    addbutton.add_widget(Button(text='hello'))

def remove(self):
    print('test')
    container = self.root.ids.mainscreen.ids.abc
    if len(container.children) > 0:
        container.remove_widget(container.children[0])

Upvotes: 2

Related Questions