You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么我的Kivy加载屏动画不动?程序出现卡顿/冻结问题?

核心问题

你遇到的应用冻结、动画卡住的问题有三个核心原因:

  1. 线程创建语法错误:Thread(target=self.spin_widget()) 这种写法会立刻在主线程执行函数,再把返回值传给target参数,完全没有实现多线程效果。正确用法是给target传函数对象,参数通过args元组传递。
  2. 耗时任务直接阻塞主线程:你在按钮on_release回调中直接调用strip_first_brief,函数内的休眠(实际场景为网络请求)会直接阻塞Kivy的UI渲染主线程,导致所有动画、交互停止。
  3. 你不需要给UI动画开子线程:Kivy的Animation本身就是异步非阻塞的,直接在主线程调用即可生效。

修复方案

1. 修改main.py

补充导入Clock,调整线程逻辑,把所有耗时任务封装到单独函数丢到子线程执行,任务完成后通过Clock调度切屏(UI操作必须在主线程执行):

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import Screen, NoTransition, CardTransition
from kivy.uix.button import ButtonBehavior
from kivy.uix.image import Image
from kivy.animation import Animation
from kivy.clock import Clock
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 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 get_briefing(self, dest1, dest2):
        # 实际场景替换为你的POST/GET请求逻辑
        time.sleep(5)

    def strip_first_brief(self, destX, etaX):
        # 实际场景替换为你的处理逻辑
        time.sleep(5)

    def process_all_tasks(self, dest1, eta1):
        # 所有耗时任务均在子线程执行
        self.get_briefing(dest1, "") # 你原代码中未定义manual_dest2,此处替换为实际参数即可
        self.strip_first_brief(dest1, eta1)
        # 任务完成后调度到主线程切屏
        Clock.schedule_once(lambda dt: self.change_screen("results_1_screen"))

TestApp().run()

2. 修改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.spin_widget()
        on_release:
            # 耗时任务丢入子线程执行
            Thread(target=app.process_all_tasks, args=(manual_dest1.text, eta1.text)).start()

修改后加载动画会全程流畅运行,不会出现卡顿,等10秒(两个sleep的总时长)后会自动切换到结果页。


内容的提问来源于stack exchange,提问作者PW1990

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 17:06:04