Para realizar una pantalla de carga en Java FX se pueden utilizar dos métodos:

  • Application con una Stage (y Scene asociada) que tras una cantidad de milisegundos arranca una nueva Stage con una Scene asociada
  • Application con una Stage (y Scene asociada) que es arrancada después de cargar un Preloader llamados desde el LauncherImpl.launchApplication()

Opción Application – Application

Se crea un fxml que muestra la interfaz gráfica que mostrará la pantalla de splash y la clase controladora que se asociará

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="splashfx.ControllerSplash">
   <children>
      <ImageView fx:id="fondo" fitHeight="400.0" fitWidth="600.0" pickOnBounds="true">
         <image>
            <Image url="@../recursos/fondo.jpg" />
         </image>
      </ImageView>
   </children>
</AnchorPane>
public class ControllerSplash implements Initializable {

    @FXML
    ImageView fondo;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
       
    }
}

Esta ventana es llamada desde el main

package splashfx;

import com.sun.deploy.util.FXLoader;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class Main extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {

        Parent root = FXMLLoader.load(getClass().getResource("vista/splashfx.fxml"));
        Scene scene = new Scene(root,600,400);
        primaryStage.setTitle("Splash Screen");
        primaryStage.setResizable(false);
        primaryStage.setScene(scene);
        primaryStage.initStyle(StageStyle.TRANSPARENT);
        primaryStage.show();

    }
}

En esta clase se asocia la parte gráfica con la ventana (Stage) y se hace visible. En la clase controladora se crea un objeto de tipo fadetransaction que se asocia un nodo de la interfaz. Cuando termina el tiempo se crea una nueva Stage – Scene que se mostrará al mismo tiempo que la actual se oculta

public class ControllerSplash implements Initializable {

    @FXML
    ImageView fondo;

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        FadeTransition transition = new FadeTransition(Duration.millis(3000),fondo);
        transition.setFromValue(1.0);
        transition.setToValue(1.0);
        transition.play();

        transition.setOnFinished(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                Stage ventana = (Stage) fondo.getScene().getWindow();
                ventana.hide();
                Stage ventanaApp = new Stage();
                Parent root = null;
                try {
                    root = FXMLLoader.load(getClass().getResource("vista/welcomefx.fxml"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Scene scene = new Scene(root,600,400);
                ventanaApp.setScene(scene);
                ventanaApp.setTitle("Pantalla principal")
                ventanaApp.show();
            }
        });

    }
}

Como se indica en el código anterior deberá de de haberse creado un archivo fxml y su controladora asociada que representa la pantalla que aparecerá tras la splash

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="splashfx.ControllerWelcome">
   <children>
      <Label layoutX="257.0" layoutY="192.0" text="BIENVENIDOS" />
   </children>
</AnchorPane>

[ezcol_1half][/ezcol_1half] [ezcol_1half_end][/ezcol_1half_end]

Opción Application – Preloader

En esta opción se realiza la llamada a las clases application y preloader  desde la clase main directamente. Para ello desde la clase Main se utiliza el método LauncherImpl.launchApplication pasando como parámetros un objeto de tipo Application, un objeto de tipo preloader y los args del método main

public class Main {
   public static void main(String[] args) {
      LauncherImpl.launchApplication(InicioFX.class, Splash.class, args);
   }
}

Por separado se crean las clases de que extienden de Application

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class InicioFX extends Application {
 
   @Override
   public void start(Stage primaryStage) throws Exception {
      Parent root = FXMLLoader.load(getClass().getResource("iniciofx.fxml"));
      Scene scene = new Scene(root);
      primaryStage.setScene(scene);
      primaryStage.show();
   }
}

y de Preloader

import javafx.application.Preloader;
import javafx.application.Preloader.StateChangeNotification.Type;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Splash extends Preloader {
private Stage stage;
 
    @Override
    public void start(Stage primaryStage) throws Exception {
       this.stage = primaryStage;
       Parent root = FXMLLoader.load(getClass().getResource("iniciofx.fxml"));
       Scene scene = new Scene(root);
       primaryStage.setScene(scene);
       primaryStage.show();
   }
 
   @Override
   public void handleStateChangeNotification(StateChangeNotification stateChangeNotification) {
      if (stateChangeNotification.getType() == Type.BEFORE_START) {
         stage.hide();
      }
   }
}

En este caso el cambio de pantalla se realiza de forma automática. Si se quiere alargar la pantalla de Splash se debería de utilizar un objeto de tipo FadeTransaction tal y como se utilizó en el ejemplo anterior (en la controladora asociada)