【问题标题】:Why doesn't my kivy load screen animation move? Stuck/frozen program?为什么我的 kivy 加载屏幕动画不动?卡住/冻结程序?
【发布时间】:2021-08-29 09:44:15
【问题描述】:

我已经使用 Kivy 开发了一段时间的应用程序,并且正在添加最后的润色。我一直在寻找几天来解决我的问题,但无济于事。我已经尝试过以各种顺序运行线程、时钟和运行功能,以尝试使其正常工作。我在下面复制了一个工作示例,但使其尽可能简约,以免使我的帖子变得庞大。在我的真实应用程序的 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

当您尝试此操作时,显然无需输入目的地或 eta。也没有提供图像,但您会在卡住之前看到方形旋转约 2 度,然后在最后一秒再次看到它试图再次旋转。我为这篇冗长的帖子道歉,但我没有其他方法可以解决这个问题。请帮忙....

【问题讨论】:

    标签: python multithreading function animation kivy


    【解决方案1】:
    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))
    

    【讨论】:

    • 非常感谢@inclement!我刚刚尝试过,它解决了许多与应用程序冻结和一起运行相关的问题。传奇,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 2022-10-18
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多