Issue
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?
Solution
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>
Answered By - SedJ601
Answer Checked By - Timothy Miller (JavaFixing Admin)