I have 2 files, Splash.java and Main.java. Here are the 2 codes: Splash.java
package application; import javafx.animation.*; import javafx.application.Application; import javafx.stage.Stage; import javafx.stage.StageStyle; import javafx.util.Duration; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import javafx.scene.paint.Color; import javafx.scene.shape.*; import javafx.scene.text.Font; /** * This is my own splash screen, that I made myself. * */ public class Splash{ static Stage splash; static Rectangle rect = new Rectangle(); public Splash() { splash = new Stage(StageStyle.UNDECORATED); splash.toFront(); splash.setHeight(200); splash.setWidth(400); } public Splash show() { /* * Part 1: * This is the rolling square animation. * This animation looks cool for a loading screen, * so I made this. Only the lines of code for fading * from Stack Overflow. */ //rectangle insertion int scale = 30; int dur = 800; rect = new Rectangle(100-2*scale,20,scale,scale); rect.setFill(Color.AQUAMARINE); //actual animations //initialising the sequentialTranslation SequentialTransition seqT = new SequentialTransition(rect); //umm, ignore this, just some configs that work magic int[] rotins = {scale,2*scale,3*scale,4*scale,5*scale,-6*scale,-5*scale,-4*scale,-3*scale,-2*scale}; int x,y; for (int i:rotins) { //rotating the square RotateTransition rt = new RotateTransition(Duration.millis(dur),rect); rt.setByAngle(i/Math.abs(i)*90); rt.setCycleCount(1); //moving the square horizontally TranslateTransition pt = new TranslateTransition(Duration.millis(dur), rect); x=(int) (rect.getX()+Math.abs(i)); y=(int) (rect.getX()+Math.abs(i)+(Math.abs(i)/i)*scale); pt.setFromX(x); pt.setToX(y); //parallelly execute them and you get a rolling square ParallelTransition pat = new ParallelTransition(); pat.getChildren().addAll(pt,rt); pat.setCycleCount(1); seqT.getChildren().add(pat); } //playing the animation seqT.play(); //lambda code sourced from StackOverflow, fades away stage seqT.setOnFinished(e->{ Timeline timeline = new Timeline(); KeyFrame key = new KeyFrame(Duration.millis(800), new KeyValue (splash.getScene().getRoot().opacityProperty(), 0)); timeline.getKeyFrames().add(key); timeline.setOnFinished((ae) -> System.exit(1)); timeline.play(); }); //The text part Label label = new Label("Flight"); label.setFont(new Font("Verdana",40)); label.setStyle("-fx-text-fill:white"); label.setLayoutX(140); label.setLayoutY(70); Label lab = new Label("Launching..."); lab.setFont(new Font("Times New Roman",10)); lab.setStyle("-fx-text-fill:white"); lab.setLayoutX(170); lab.setLayoutY(180); //A complimentary image Image image = new Image(getClass().getResourceAsStream("launchplane.png")); ImageView iv = new ImageView(image); iv.setFitWidth(32); iv.setFitHeight(32); iv.setX(174); iv.setY(130); //now adding everything to position, opening the stage, start the animation Pane pane = new Pane(rect,label,lab,iv); pane.setStyle("-fx-background-color:black"); Scene sc = new Scene(pane); splash.setScene(sc); splash.show(); seqT.play(); return this; } }
And Main.java
package application; import javafx.application.Application; import javafx.application.Platform; import javafx.fxml.FXMLLoader; import javafx.stage.Stage; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.image.Image; import javafx.scene.layout.BorderPane; public class Main extends Application { @Override public void start(Stage primaryStage) { try { Parent root = FXMLLoader.load(getClass().getResource("main.fxml")); Scene scene = new Scene(root); scene.getStylesheets().add( getClass().getResource("application.css").toExternalForm()); primaryStage.setTitle("Flight"); primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("airplane.png"))); primaryStage.setScene(scene); Splash splash = new Splash(); splash.show(); primaryStage.toBack(); primaryStage.show(); } catch(Exception e) { e.printStackTrace(); } } public static void main(String[] args) { launch(args); } }
Now I want to make a Splash screen appear before the main program is launched. How do I modify Main.java so that my code can show the splash screen for its entire duration before fading away and opening the main program?
Advertisement
Answer
I made a few changes to your code. I changed the Splash
variable to Scene
. I then added methods to get the Scene
and the SequentialTransition
. I set the SequentialTransition
onFinished method in the main.
.
Main
import java.io.IOException; import javafx.animation.KeyFrame; import javafx.animation.KeyValue; import javafx.animation.Timeline; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import javafx.util.Duration; /** * * @author blj0011 */ public class JavaFXApplication266 extends Application { @Override public void start(Stage stage) throws Exception { Splash splash = new Splash(); splash.show(); stage.setScene(splash.getSplashScene()); splash.getSequentialTransition().setOnFinished(e -> { Timeline timeline = new Timeline(); KeyFrame key = new KeyFrame(Duration.millis(800), new KeyValue(splash.getSplashScene().getRoot().opacityProperty(), 0)); timeline.getKeyFrames().add(key); timeline.setOnFinished((event) -> { try { Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml")); // Scene scene = new Scene(root); stage.setScene(scene); } catch (IOException ex) { ex.printStackTrace(); } }); timeline.play(); }); // stage.show(); } /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } }
Splash Class
import javafx.animation.*; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import javafx.scene.paint.Color; import javafx.scene.shape.*; import javafx.scene.text.Font; import javafx.util.Duration; /** * This is my own splash screen, that I made myself. * */ public class Splash { static Scene splash; static Rectangle rect = new Rectangle(); final private Pane pane; final private SequentialTransition seqT; public Splash() { pane = new Pane(); pane.setStyle("-fx-background-color:black"); splash = new Scene(pane); seqT = new SequentialTransition(); } public void show() { /* * Part 1: * This is the rolling square animation. * This animation looks cool for a loading screen, * so I made this. Only the lines of code for fading * from Stack Overflow. */ //rectangle insertion int scale = 30; int dur = 800; rect = new Rectangle(100 - 2 * scale, 20, scale, scale); rect.setFill(Color.AQUAMARINE); //actual animations //initialising the sequentialTranslation //umm, ignore this, just some configs that work magic int[] rotins = {scale, 2 * scale, 3 * scale, 4 * scale, 5 * scale, -6 * scale, -5 * scale, -4 * scale, -3 * scale, -2 * scale}; int x, y; for (int i : rotins) { //rotating the square RotateTransition rt = new RotateTransition(Duration.millis(dur), rect); rt.setByAngle(i / Math.abs(i) * 90); rt.setCycleCount(1); //moving the square horizontally TranslateTransition pt = new TranslateTransition(Duration.millis(dur), rect); x = (int) (rect.getX() + Math.abs(i)); y = (int) (rect.getX() + Math.abs(i) + (Math.abs(i) / i) * scale); pt.setFromX(x); pt.setToX(y); //parallelly execute them and you get a rolling square ParallelTransition pat = new ParallelTransition(); pat.getChildren().addAll(pt, rt); pat.setCycleCount(1); seqT.getChildren().add(pat); } //playing the animation seqT.play(); //lambda code sourced from StackOverflow, fades away stage seqT.setNode(rect); //The text part Label label = new Label("Flight"); label.setFont(new Font("Verdana", 40)); label.setStyle("-fx-text-fill:white"); label.setLayoutX(140); label.setLayoutY(70); Label lab = new Label("Launching..."); lab.setFont(new Font("Times New Roman", 10)); lab.setStyle("-fx-text-fill:white"); lab.setLayoutX(170); lab.setLayoutY(180); //A complimentary image Image image = new Image("https://s3.amazonaws.com/media.eremedia.com/uploads/2012/08/24111405/stackoverflow-logo-700x467.png"); ImageView iv = new ImageView(image); iv.setFitWidth(32); iv.setFitHeight(32); iv.setX(174); iv.setY(130); //now adding everything to position, opening the stage, start the animation pane.getChildren().addAll(rect, label, lab, iv); seqT.play(); } public Scene getSplashScene() { return splash; } public SequentialTransition getSequentialTransition() { return seqT; } }
After Splash Controller
import java.net.URL; import java.util.ResourceBundle; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Label; /** * * @author blj0011 */ public class FXMLDocumentController implements Initializable { @FXML private Label label; @FXML private void handleButtonAction(ActionEvent event) { System.out.println("You clicked me!"); label.setText("Hello World!"); } @Override public void initialize(URL url, ResourceBundle rb) { // TODO } }
After Splash FXML
<?xml version="1.0" encoding="UTF-8"?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication266.FXMLDocumentController"> <children> <Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" /> <Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" /> </children> </AnchorPane>