I am making a loading screen for an app and have a little problem with running an animation and an algorithm (which takes a long time to run) at the same time. However when I run that chunk of code, I get the error AttributeError: 'super' object has no attribute 'getattr' when i try call 'self.ids.loading_anim'. Can anybody reccomend a better way to multithread an animation in kivy? Bear in mind that when I multithread the other algorithm, it takes too long to run.
Python code:
def animate_image(self):
anim = Animation()
anim.start(self.ids.loading_anim)
class LoadingWindow(Screen):
def on_enter(self):
t = Thread(target=animate_image, args=(self))
t.deamon = True
t.start()
for x in range(5):
print(x) # this is just a test algorithm which takes 5 seconds to run
time.sleep(1) # in the real file there is another algorithm which takes time to run
Kivy Code
<LoadingWindow>
FloatLayout:
Image:
id: animation
source: 'loading.gif'
size_hint_x:0.6
size_hint_y:0.6
pos_hint: {'x':0.19, 'y':0.2}
allow_stretch: True
anim_delay: 0
anim_reset: True
Label:
text: 'Searching the internet for recipes....'
pos_hint: {'x':0, 'y':0.3}
font_size: 28
CodePudding user response:
First of all , I think the function animate_image() can be placed inside the class ?
and the error you get is because self.ids
don't have a key called loading_anim
, I think it should be animation
by referencing to the .kv file ?
on the other hand , I think you can also thread the algorithm as well ?
I also added the class MyApp
with Inherit to the kivy.app.App and put the LoadingWindow class to kivy ScreenManager. See if this is what you want.
from threading import Thread
import time
import kivy
from kivy.clock import Clock
from kivy.app import App
from kivy.animation import Animation
from kivy.uix.screenmanager import Screen, ScreenManager
kivy.lang.Builder.load_string("""
#:kivy 2.0.0
<LoadingWindow>
FloatLayout:
Image:
id: animation
source: 'loading.gif'
size_hint_x:0.6
size_hint_y:0.6
pos_hint: {'x':0.19, 'y':0.2}
allow_stretch: True
anim_delay: 0
anim_reset: True
Label:
text: 'Searching the internet for recipes....'
pos_hint: {'x':0, 'y':0.3}
font_size: 28
""")
class LoadingWindow(Screen):
def animate_image(self): # can you put the animate_image() function to here ?
anim = Animation()
# anim.start(self.ids.loading_anim) # I think it should be animation ref to the .kv file ?
anim.start(self.ids.animation)
def your_algorithm(self):
for x in range(5):
print(x) # this is just a test algorithm which takes 5 seconds to run
time.sleep(1) # in the real file there is another algorithm which takes time to run
def on_enter(self):
t = Thread(target = self.animate_image)
t.deamon = True
t.start()
# instead of threading the animation , I think you can also thread the algorithm ?
algorithm = Thread(target = self.your_algorithm)
algorithm.start()
class MyApp(App):
screen_manager = ScreenManager()
def build(self):
# add screen to screen manager
self.screen_manager.add_widget(LoadingWindow(name = "LoadingWindow"))
return self.screen_manager
MyApp().run()
any other suggestions / recommendations / better method / etc. is welcome : )
( sry for bad English )
CodePudding user response:
i have similar problems with on_pre_enter
& on_enter
from my knowledge the function on_pre_enter
and on_enter
is called before the screen ids loaded but i found a way you can use
try this code:
from kivy.clock import Clock
def animate_image(self):
anim = Animation()
anim.start(self.ids.loading_anim)
class LoadingWindow(Screen):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Clock.schedule_once(self.init_completed)
def init_completed(self, dt):
t = Thread(target=animate_image, args=(self))
t.deamon = True
t.start()
for x in range(5):
print(x) # this is just a test algorithm which takes 5 seconds to run
time.sleep(1) # in the real file there is another algorithm which takes time to run
as i said in the Screen
on_pre_enter
and on_enter
is called before ids loaded but with this way the ids are loaded then your function init_completed is called
worked for me.