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
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()