Kivy 不在 Popup 中播放 gif 而其他代码是 运行

Kivy does not play gif in Popup while other code is running

在我的 Kivy 应用程序中,我有一个功能需要很长时间才能完成。我做了一个弹出窗口来通知用户函数是 运行ning。我想要一个 gif 动画,以便用户知道该应用程序没有崩溃。在测试中,gif 在弹出窗口中按预期播放,直到我添加 long 运行ning 函数,然后才显示静止图像。其他一切都按预期工作(例如弹出窗口在函数结束时关闭)。

tl;dr

如何让 gif 在我的 kivy 应用程序中在执行功能时继续播放?

代码摘要

我基本上遵循了 Dirty Penguin 在 Building a simple progress bar or loading animation in Kivy? 中的回答提供的代码:

from kivy.app import App
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty
from kivy.clock import Clock

import time, threading

class RunningPopup(GridLayout):
    fpop = None

    def set_pop(self, pwin):
        self.fpop = pwin

    def close(self):
        self.fpop.dismiss()

class ExampleApp(App):
    def show_popup(self):
        self.pop_up = RunningPopup()
        self.pop_up.open()

    def process_button_click(self):
        # Open the pop up
        self.show_popup()

        # the original code suggested by dirty penguin
        # mythread = threading.Thread(target=self.really_long_function)
        # mythread.start()

        # I've had better luck with the Clock.schedule_once
        Clock.schedule_once(self.really_long_function)

    def really_long_function(self):
        thistime = time.time() 
        while thistime + 5 > time.time(): # 5 seconds
            time.sleep(1)

        # Once the long running task is done, close the pop up.
        self.pop_up.dismiss()

if __name__ == "__main__":
    ExampleApp().run()

我的 KV 文件:

<RunningPopup>:
    rows: 3

    Label:
        size_hint_y: 0.2
        text: 'Experiments are running ... '
        bold: True
        color: hex('#0DB14B')

    Label:
        size_hint_y: 0.2
        text: 'Please be patient, this may take time.'
        color: hex('#0DB14B')

    Image:
        size_hint_y: 0.6
        id: loading_animation_gif
        height: dp(200)
        source: './graphics/loading.gif'
        center_x: self.parent.center_x
        center_y: self.parent.center_y
        allow_stretch: True
        size_hint_y: None
        anim_delay: 0.05
        mipmap: True

尝试过

相关

使用 Thread 即可。这是使用线程的代码的修改版本。我必须进行一些更改才能使您的代码变为 运行:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.popup import Popup

import time, threading

kv = '''
#:import hex kivy.utils.get_color_from_hex
Button:
    text: 'doit'
    on_release: app.process_button_click()
    
<RunningPopup>:
    GridLayout:
        rows: 3
    
        Label:
            size_hint_y: 0.2
            text: 'Experiments are running ... '
            bold: True
            color: hex('#0DB14B')
    
        Label:
            size_hint_y: 0.2
            text: 'Please be patient, this may take time.'
            color: hex('#0DB14B')
    
        Image:
            size_hint_y: 0.6
            id: loading_animation_gif
            height: dp(200)
            source: 'elephant.gif'  # my gif file
            center_x: self.parent.center_x
            center_y: self.parent.center_y
            allow_stretch: True
            size_hint_y: None
            anim_delay: 0.05
            mipmap: True
'''

class RunningPopup(Popup):
    fpop = None

    def set_pop(self, pwin):
        self.fpop = pwin

    def close(self):
        self.fpop.dismiss()

class ExampleApp(App):
    def build(self):
        return Builder.load_string(kv)

    def show_popup(self):
        self.pop_up = RunningPopup()
        self.pop_up.open()

    def process_button_click(self):
        # Open the pop up
        self.show_popup()

        # the original code suggested by dirty penguin
        mythread = threading.Thread(target=self.really_long_function)
        mythread.start()

        # I've had better luck with the Clock.schedule_once
        # Clock.schedule_once(self.really_long_function)

    def really_long_function(self, *args):
        thistime = time.time()
        while thistime + 5 > time.time(): # 5 seconds
            time.sleep(1)

        # Once the long running task is done, close the pop up.
        self.pop_up.dismiss()

if __name__ == "__main__":
    ExampleApp().run()