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)