为什么我的 kivy 加载屏幕动画不移动? Stuck/frozen 节目?

Why doesn't my kivy load screen animation move? Stuck/frozen program?

我已经使用 Kivy 开发应用程序一段时间了,现在正在做最后的润色。几天来我一直在寻找解决我的问题的方法,但无济于事。我已经按各种顺序尝试了 Threading、Clock 和 运行 函数,以尝试使其正常工作。我在下面复制了一个工作示例,但尽可能简化了它,以免使我的 post 变大。在我真实应用程序的 get_briefingstrip_first_brief 函数中,我有几个 POST 请求和几个 GET 请求,执行时间从 5 到 20 秒不等。因此,我在每一个中都实现了 time.sleep(5) 来模拟工作时间。这给出了与我的真实应用程序完全相同的结果。停止动画的不仅仅是 POST 或 GET 函数,而是涉及的每个进程....

由于这些加载时间,我还切入一个角落进入我的加载屏幕,其中我的按钮 on_press 立即更改屏幕,否则随着卡片转换,屏幕卡在大约 1/5 到过渡。在这个程序中我显然有不止一个问题需要解决,我认为如果我能解决“冻结的应用程序”问题,大多数问题都会得到解决...

如果有人可以复制并测试我提供的程序,并提供解决方案,我将不胜感激。我在这个问题上被困了太久了(字面意思)。

main.py

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, NoTransition, CardTransition, SwapTransition
from kivy.uix.button import ButtonBehavior
from kivy.uix.image import Image
from kivy.animation import Animation
import time
from threading import Thread

class ImageButton(ButtonBehavior, Image):
    pass
class HomeScreen(Screen):
    pass
class Results1Screen(Screen):
    pass
class LoadScreen(Screen):
    pass

GUI = Builder.load_file("main.kv")
class TestApp(App):
    def build(self):
        return GUI

    def change_screen(self, screen_name):
        screen_manager = self.root.ids['screen_manager']
        screen_manager.current = screen_name

    def widget_thread(self):
        p1 = Thread(target=self.spin_widget())
        p1.start()
        #Clock.schedule_once(lambda dt: self.spin_widget(), 0)

    def spin_widget(self):
        widget = self.root.ids["load_screen"].ids["spinning_widget"]
        anim = Animation(angle=-3000, duration=40)
        anim.start(widget)

    def immediate_screen1(self):
        self.root.ids["screen_manager"].transition = NoTransition()
        self.change_screen("load_screen")
        self.root.ids["screen_manager"].transition = CardTransition()

    def thread1(self, dest1, dest2):
        self.thread = 1
        p2 = Thread(target=self.get_briefing(dest1, dest2))
        p2.start()

    def get_briefing(self, dest1, dest2):
        time.sleep(5)

    def strip_first_brief(self, destX, etaX):
        time.sleep(5)
        #p3 = Thread(self.strip_first_brief(dest2, eta2))
        #p3.start()

TestApp().run()

main.kv

#:import utils kivy.utils
#:include kv/homescreen.kv
#:include kv/results1screen.kv
#:include kv/loadscreen.kv
GridLayout:
    cols: 1
    FloatLayout:
        canvas:
            Color:
                rgb: utils.get_color_from_hex("#000523")
            Rectangle:
                size: self.size
                pos: self.pos
        rows: 1
        pos_hint: {"top": 1, "left": 1}
        size_hint: 1, .04
    ScreenManager:
        size_hint: 1, .8
        pos_hint: {"top": .8, "left": 1}
        id: screen_manager
        HomeScreen:
            name: "home_screen"
            id: home_screen
        Results1Screen:
            name: "results_1_screen"
            id: results_1_screen
        LoadScreen:
            name: "load_screen"
            id: load_screen

homescreen.kv

<HomeScreen>:
    FloatLayout:
        canvas:
            Color:
                rgb: utils.get_color_from_hex("#000523")
            Rectangle:
                size: self.size
                pos: self.pos
    TextInput:
        id: manual_dest1
        hint_text: "first destination"
        text: self.text.upper() if self.text is not None else ''
        size_hint: .7, .08
        pos_hint: {"top": .75, "center_x": .5}
    TextInput:
        id: eta1
        hint_text: "first ETA in UTC"
        text: self.text.upper() if self.text is not None else ''
        size_hint: .7, .08
        pos_hint: {"top": .5, "center_x": .5}
    Button:
        text: "Strip TAF"
        pos_hint:  {"top": .15, "center_x": .5}
        size_hint: .5, .08
        padding: 20, 20
        opacity: 1 if self.state == 'normal' else .5
        on_press:
            app.immediate_screen1()
            app.widget_thread()
        on_release:
            app.thread1(manual_dest1.text, manual_dest2.text)
            app.strip_first_brief(manual_dest1.text, eta1.text)
            app.change_screen("results_1_screen")

results1screen.kv

<Results1Screen>:
    FloatLayout:
        canvas:
            Color:
                rgb: utils.get_color_from_hex("#000523")
            Rectangle:
                size: self.size
                pos: self.pos
    Label:
        rows: 1
        text: "RESULTS\nblah\nblah\nblah"
        pos_hint: {"top": .95, "center_x": .5}
        size_hint: 1, .05

loadscreen.kv

<LoadScreen>:
    FloatLayout:
        canvas:
            Color:
                rgb: utils.get_color_from_hex("#000523")
            Rectangle:
                size: self.size
                pos: self.pos
        Label:
            text: "loading"
        SpinningWidget:
            id: spinning_widget
            source: "icons/turbine.png"
            angle: 0
            size_hint: .15, .15
            pos_hint: {"center_x": .5, "center_y": .6}
<SpinningWidget@Image>
    angle: 0
    canvas.before:
        PushMatrix
        Rotate:
            angle: root.angle
            axis: 0, 0, 1
            origin: root.center
    canvas.after:
        PopMatrix

当你尝试这个时,显然不需要输入目的地或预计到达时间。也没有提供图像,但你会看到正方形在卡住之前旋转了大约 2 度,然后在最后一秒再次看到它试图再次旋转。对于冗长的post,我深表歉意,但我没有其他方法可以解决这个问题。请帮助....

p2 = Thread(target=self.get_briefing(dest1, dest2))

这个 调用 self.get_briefing 并将结果传递给目标,即它等同于:

result = self.get_briefing(dest1, dest2)
p2 = Thread(target=result)

你可能想传入要调用的函数作为参数,比如

p2 = Thread(target=lambda: self.get_briefing(dest1, dest2))