Search code examples
pythonkivykivy-languagekivymd

add_widget and remove_widget for a class in kivy


Im new to Kivy, Im sorry for asking 2 questions in a post..

First, why the remove_widget() does not work? It said AttributeError: 'MyCard' object has no attribute 'remove_card' but I tried to put them in other classes and it still does not work.

Second, why my widgets are still have "focus behavior" and my buttons are still clickable even when I put a card whose color has little transparent on it

This is my main.py file

class MyCard(Screen):
    pass

class HomeScreen(Screen):
    def add_card(self):
        self.add_widget(MyCard())
    def remove_card(self):
        self.remove_widget(MyCard(name='cardd'))

class AVCard(Screen):
    pass

class ScreenApp(MDApp):
    def build(self):
        def build(self):
    sm = ScreenManager(transition=FadeTransition(duration=0.2))
    sm.add_widget(HomeScreen(name='home'))
    sm.add_widget(AVCard(name='av'))
    return sm

and this is my home.kv file (AVCard class has its own .kv file)

<HomeScreen>:
    name: 'home'
    MDIconButton:
        on_release: root.add_card()
        ...

<MyCard>:
    name: 'cardd'
    MDCard: #-> I put this card is to not allow user click on widgets behind it but it does not work
        md_bg_color: 0, 0, 0, .3
        ...
    MDCard: #-> Thís card is like a window which includes small widgets in it
        ...
        Screen:
            MDIconButton: #-> The close button
                icon: "close-circle"
                ...
                on_release:
                    root.remove_card()

Thank you very much.


Solution

  • In your kv, the root.remove_card() is trying to reference the remove_card() method of root. In this instance root refers to the root of the rule in which it appears, which is the MyCard. That is why you see the error message, the remove_card() is not in the MyCard object. The fix is to use a reference to the correct object that does contain the remove_card() method, like this:

    <MyCard>:
        MDCard: #-> I put this card is to not allow user click on widgets behind it but it does not work
            md_bg_color: 0, 0, 0, .3
        MDCard: #-> Thís card is like a window which includes small widgets in it
            Screen:
                MDIconButton: #-> The close button
                    icon: "close-circle"
                    on_release:
                        app.root.get_screen('home').remove_card(root)
    

    Note the use of app.root.get_screen('home').remove_card(root), this gets a reference to the HomeScreen object (assuming the name used is home), and calls its remove_card() method with root (the MyCard instance) as an arg.

    Then , in the HomeScreen class, the remove_card() method can be:

    def remove_card(self, card):
        self.remove_widget(card)