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

如何在JavaFX启动画面(SplashScreen)中显示动态GIF或视频?

JavaFX SplashScreen 中动态GIF/视频无法播放的解决办法

你遇到的问题根源在于JavaFX应用线程被阻塞了——你在Main类的start方法里调用了Thread.sleep(5000),这个方法会直接卡住负责UI渲染(包括GIF动画帧更新)的应用线程,导致启动画面的GIF完全没法播放,直到sleep结束、主界面加载完成后,线程空闲下来才会开始动。

要解决这个问题,核心思路是把耗时的初始化逻辑(比如你模拟的后端加载)放到后台线程中执行,让JavaFX应用线程能专心处理启动画面的渲染和动画。我们可以用JavaFX自带的Task来实现安全的后台任务,它能自动处理和UI线程的交互。

修改后的代码实现

1. 优化Main类(移除线程阻塞逻辑)

package com.example;
import javafx.application.Application;
import javafx.application.Preloader.StateChangeNotification;
import javafx.concurrent.Task;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class Main extends Application{
    Stage stage;
    Scene scene;

    @Override
    public void start(Stage primaryStage) throws Exception {
        this.stage = primaryStage;

        // 创建后台任务处理耗时加载
        Task<Void> loadTask = new Task<>() {
            @Override
            protected Void call() throws Exception {
                // 模拟后端加载过程,运行在后台线程,不会阻塞UI
                Thread.sleep(5000);
                return null;
            }
        };

        // 任务完成后,在UI线程加载主界面并通知预加载器关闭启动画面
        loadTask.setOnSucceeded(event -> {
            try {
                FXMLLoader mainLoader = new FXMLLoader(getClass().getClassLoader().getResource("layouts/main.fxml"));
                AnchorPane pane = mainLoader.load();
                scene = new Scene(pane, 600, 445);
                primaryStage.setScene(scene);
                primaryStage.show();
                notifyPreloader(new StateChangeNotification(StateChangeNotification.Type.BEFORE_START));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        // 启动后台任务
        new Thread(loadTask).start();
    }
}

2. (可选)启动画面播放视频的实现

如果要在启动画面播放视频,只需修改SplashScreen类和对应的fxml文件:

修改后的splash.fxml

<StackPane xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <MediaView fx:id="mediaView" fitHeight="374.0" fitWidth="686.0" pickOnBounds="true" preserveRatio="true"/>
    </children>
</StackPane>

修改后的SplashScreen类

package com.example;
import javafx.application.Preloader;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.layout.StackPane;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class SplashScreen extends Preloader {
    Stage stage;
    private MediaPlayer mediaPlayer;

    @Override
    public void start(Stage stage) throws Exception {
        this.stage = stage;
        FXMLLoader loader = new FXMLLoader(getClass().getClassLoader().getResource("layouts/splash.fxml"));
        StackPane root = loader.load();

        // 初始化视频播放器
        Media media = new Media(getClass().getResource("/test.mp4").toExternalForm());
        mediaPlayer = new MediaPlayer(media);
        MediaView mediaView = loader.getNamespace().get("mediaView");
        mediaView.setMediaPlayer(mediaPlayer);
        // 设置循环播放
        mediaPlayer.setCycleCount(MediaPlayer.INDEFINITE);
        mediaPlayer.play();

        Scene scene = new Scene(root, 690, 380, true, SceneAntialiasing.BALANCED);
        scene.setFill(Color.TRANSPARENT);
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setScene(scene);
        stage.show();
    }

    @Override
    public void handleApplicationNotification(PreloaderNotification pn) {
        if (pn instanceof StateChangeNotification) {
            // 停止视频播放并关闭启动窗口
            mediaPlayer.stop();
            stage.hide();
        }
    }
}

核心原理总结

不管是GIF还是视频,它们的渲染/播放都依赖JavaFX应用线程的正常运行。只要把所有耗时操作移到后台线程,让UI线程保持空闲,启动画面的动态内容就能正常播放了。

内容的提问来源于stack exchange,提问作者Jawad El Fou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:12:34