3

Is it possible to have an animated gif or video in my splash screen.

Here is my code

Launcher class: ** EDITED With all needed files to run simple project.

package com.example;
import javafx.application.Application;
public class Launcher 
{    
    public static void main(String[] args) {  
        System.setProperty("javafx.preloader", "com.example.SplashScreen");      
        Application.launch(Main.class);        
    }
}

Main class

package com.example;
import javafx.application.Application;
import javafx.application.Preloader.StateChangeNotification;
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 {
    
    try {
        Thread.sleep(5000);
        this.stage = primaryStage;
        AnchorPane pane;
        FXMLLoader mainLoader = new FXMLLoader(getClass().getClassLoader().getResource("layouts/main.fxml"));   
        pane = mainLoader.load();                                               
        scene = new Scene(pane, 600, 445);
        primaryStage.setScene(scene);
        
        primaryStage.show();
        notifyPreloader(new StateChangeNotification(StateChangeNotification.Type.BEFORE_START));
        
    } 
    catch (final Exception e) {
        e.printStackTrace();
    }        
}

}

SplashScreenClass

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.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class SplashScreen extends Preloader {

    Stage stage;

@Override
public void start(Stage stage) throws Exception {
    this.stage = stage;
    StackPane root = (StackPane) FXMLLoader.load(getClass().getClassLoader().getResource("layouts/splash.fxml"));        
    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) {
        //hide after get any state update from application
        stage.hide();
    }
}  

}

So basically this is all the java code needed. I added a sleep for 5 seconds to simulate loading from backend. This will generate a splash screen but the gif is not animated. If I do no hide the splashscreen stage, the gif will be animated after the main stage is loaded.

splash fxml

<StackPane xmlns="http://javafx.com/javafx/15.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <StackPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="380.0" prefWidth="690.0">
     <children>
        <ImageView fitHeight="374.0" fitWidth="686.0" pickOnBounds="true" preserveRatio="true">
           <image>
              <Image url="@../test.gif" />
           </image>
        </ImageView>
     </children>
  </StackPane>

and finally main.fxml

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" >
   <children>      
      <Label layoutX="238.0" layoutY="224.0" prefHeight="63.0" prefWidth="125.0" text="Label" />
   </children>
</AnchorPane>
Jawad El Fou
  • 313
  • 2
  • 11
  • Does the GIF work otherwise (i.e. does it animate when shown in the "main" part of the application)? – Slaw Sep 18 '21 at 18:15
  • 1
    Yes it does if I load it whilst the application is running it will show and animate. – Jawad El Fou Sep 18 '21 at 18:34
  • You can add an image inline to the question. Please do so for your gif image. – jewelsea Sep 18 '21 at 22:33
  • 2
    I’m guessing the error is in code you don’t show. Please edit the question to provide an [mcve], minimal code someone can copy and paste without change or addition, to replicate the issue. Most likely you are performing some long running task on the JavaFX thread. – jewelsea Sep 18 '21 at 22:36
  • I am guessing it is not but will do – Jawad El Fou Sep 19 '21 at 03:06
  • Do you also need the pom file or this is sufficient? – Jawad El Fou Sep 19 '21 at 03:37
  • 3
    Sleeping in the start function is a “long running task on the JavaFX thread”. Your comment said you added it to simulate “simulate loading from backend”, so that would also be a long running task on the JavaFX thread. You can research Tasks and concurrency in JavaFX (run a web search) to see how to address that. – jewelsea Sep 19 '21 at 08:59
  • @jewelsea So I thought the preloader will run in a different thread. I guess I was wrong and this is why the preloader gif is not animated. – Jawad El Fou Sep 20 '21 at 00:40
  • Related [task based splash example](https://gist.github.com/jewelsea/2305098). – jewelsea Sep 20 '21 at 01:50

1 Answers1

1

Thanks to the @jewelsea comment, I ended up modifying the main class to do tasks in a background thread and then, when everything is ready, I show the stage for the main application.

[...]
    
    try {
        final Task<Integer> task = new Task<Integer>() {
            @Override
            protected Integer call() throws Exception {
                Thread.sleep(5000);
                Platform.runLater(new Runnable() {
                    public void run() {
                        showStage();
                    }
                }); 
                return 0;
            }
        };
        
        Thread thread = new Thread(task);
        thread.start();
    } catch (final Exception e) {
        e.printStackTrace();
    }
}

public void showStage() {
    stage.show();
    notifyPreloader(new StateChangeNotification(StateChangeNotification.Type.BEFORE_START));
}

The GIF is animated and the splash screen will load after all background tasks are done.

Jawad El Fou
  • 313
  • 2
  • 11