简体   繁体   English

如何将 animation 放在 kivy 的线程上

[英]How to put an animation on a thread in kivy

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.我正在为应用程序制作加载屏幕,同时运行 animation 和算法(需要很长时间才能运行)时遇到了一点问题。 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'.但是,当我运行该代码块时,当我尝试调用“self.ids.loading_anim”时,出现错误 AttributeError: 'super' object has no attribute ' getattr '。 Can anybody reccomend a better way to multithread an animation in kivy?有人可以推荐一种更好的方法来多线程 kivy 中的 animation 吗? Bear in mind that when I multithread the other algorithm, it takes too long to run.请记住,当我对其他算法进行多线程处理时,运行时间太长。

Python code: Python代码:

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 Kivy代码

<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
        

First of all, I think the function animate_image() can be placed inside the class?首先,我认为 function animate_image() 可以放在 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?你得到的错误是因为self.ids没有一个名为loading_anim的键,我认为通过引用.kv 文件应该是animation

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.我还添加了 class MyApp并继承到 kivy.app.App 并将 LoadingWindow class 到 Z0BB1390C49DB63D0A4B1390C49DB6100A4B1390C49DB63D3 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 ) (抱歉英语不好)

i have similar problems with on_pre_enter & on_enter我对on_pre_enteron_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据我所知,function on_pre_enteron_enter在屏幕 ID 加载之前被调用,但我找到了一种可以使用的方法

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正如我在Screen上所说的on_pre_enteron_enter在 ids 加载之前被调用但是通过这种方式加载 ids 然后你的 function init_completed 被调用

worked for me.为我工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM