Search code examples
pythonclasskivykivymd

Button in a separate class and file not working in KivyMD


I just started Kivy and I'm using a mix of Kivy and KivyMD. I made a simple button that is in a separate file and class and added it to my main class. It is supposed to just print 'WORKS' but it don't

This is my main.py:

from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from audio_player import AudioPlayer

class Demo(MDApp):
    def build(self):
        screen = MDScreen()
        player = AudioPlayer()

        btn = player.playerBTN()
        screen.add_widget(btn)
        return screen
    

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

And this is the button file located in audio_player.py:

from kivymd.uix.button import MDRectangleFlatButton
from kivy.core.audio import SoundLoader

class AudioPlayer():

    def playerBTN(self, xPos=0.5, yPos=0.3):    
        return MDRectangleFlatButton(text='X', pos_hint={
                                    'center_x': xPos, 'center_y': yPos},
                                    on_release=self.btnfunc)
    
    def btnfunc(self, obj):
        print('WORKS')

And when I click on the button, nothing happends. No error, no statement. I tried solving this for too long but it is probably something dumb.


Solution

  • The problem is that in your build() method you create an instance of AudioPlayer, and use that instance to call playerBTN(). But you do not use or save the AudioPlayer instance, so it is quickly garbage collected. The result is that when you press the Button, the btnfunc() is no longer available since its containing class has been garbage collected. One fix is to just keep a reference to the AudioPlayer instance, which eliminates its garbage collection:

    class Demo(MDApp):
        def build(self):
            screen = MDScreen()
            self.player = AudioPlayer()  # save a reference to the AudioPlayer to avoid garbage collection
    
            btn = self.player.playerBTN()
            screen.add_widget(btn)
            return screen