Home > front end >  How to put an animation on a thread in kivy
How to put an animation on a thread in kivy

Time:01-01

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.

  • Related