【问题标题】:Kivy does not play gif in Popup while other code is runningKivy 不在 Popup 中播放 gif 而其他代码正在运行
【发布时间】:2021-06-22 21:23:18
【问题描述】:

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

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

试过

  • 使用线程 - 这不并行运行,长函数运行,然后弹出窗口闪烁打开和关闭
  • 使用 kivy.clock schedule_once - 这似乎效果最好,因为弹出窗口按预期打开和关闭/在长时间运行的功能期间
  • 使用图像的 Zip 文件而不是 gif 文件(此处建议:Gif Animation not playing in Kivy App

相关

【问题讨论】:

  • Kivy 与任何其他 GUI 框架一样,有一个循环来处理事件。如果您通过运行其他程序来阻止该循环,则 GUI 会停止运行。

标签: python kivy kivy-language


【解决方案1】:

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

【讨论】:

  • 此解决方案有效。非常感谢 - 我之前在 python 中没有大量使用线程 - 我尝试过线程,但没有使用正确的语法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-26
  • 2023-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-05
  • 1970-01-01
相关资源
最近更新 更多