Search code examples
pythonkivyanimated-gif

Kivy: returning animated gif and then calling another def


After a button is clicked, the app is supposed to display a very heavy table so I would like to first display an animated gif and then display the table.

When the button is clicked, a first def is called with this:

wait_image= Loading()
self.add_widget(wait_image)
Clock.schedule_once(lambda x: self.DisplayTable(self), 0)

But this only load the first frame of the animated gif. If I replace the Clock.schedule by return self, then the animated gif works but the DisplayTable def isn't called:

wait_image= Loading()
self.add_widget(wait_image)
return self

I tried to call another def that will return self, and then proceed with th DisplayTable but this also doesn't work (the .gif isn't animated but the table is displayed):

Loading_image(self)
Clock.schedule_once(lambda x: self.DisplayTable(self), 0)

with :

def Loading_image(self):
    wait_image= Loading()
    self.add_widget(wait_image)
    return self

So how can I, with a simple click, called and display an animated gif and then proceed to call the DisplayTable def?


Here is the Builder and the Loading class:

Builder.load_string('''
<Loading>
    source : 'loading.zip'
    anim_delay : 0.02
    allow_stretch : True
    keep_ratio : True
    keep_data : True
''')
class Loading(AsyncImage):
    pass

The code is here


Solution

  • You need to let the event loop time to update your gif... Using kivyoav makes it simple:

    from kivyoav.delayed import delayable
    
    @delayable
    def DisplayTable(self):
        for i in ROWS:
            yield 0.01 # after each row the gif will have time to update ... 
            for j in COLS:
                pass # build your table cols ...
    

    Another choice is to do the heavy lifting in a different thread and only update the UI later using Clock.schedule_once

    def build_table():
       ...
       #stuff that take time
       stuff = ...
       ...
       Clock.schedule_once(lambda dt: build_ui_table(stuff)) #since you can use the UI only from the main thread
    threading.Thread(target=build_table).start()