Skip to content

Instantly share code, notes, and snippets.

@jewelsea
Last active February 26, 2024 13:33
Show Gist options
  • Save jewelsea/2305098 to your computer and use it in GitHub Desktop.
Save jewelsea/2305098 to your computer and use it in GitHub Desktop.
Displays a JavaFX splash page for an intensive startup task with progress monitoring
import javafx.animation.FadeTransition;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.collections.*;
import javafx.concurrent.*;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.effect.DropShadow;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.stage.*;
import javafx.util.Duration;
/**
* Example of displaying a splash page for a standalone JavaFX application
*/
public class FadeApp extends Application {
public static final String APPLICATION_ICON =
"http://cdn1.iconfinder.com/data/icons/Copenhagen/PNG/32/people.png";
public static final String SPLASH_IMAGE =
"http://fxexperience.com/wp-content/uploads/2010/06/logo.png";
private Pane splashLayout;
private ProgressBar loadProgress;
private Label progressText;
private Stage mainStage;
private static final int SPLASH_WIDTH = 676;
private static final int SPLASH_HEIGHT = 227;
public static void main(String[] args) throws Exception {
launch(args);
}
@Override
public void init() {
ImageView splash = new ImageView(new Image(
SPLASH_IMAGE
));
loadProgress = new ProgressBar();
loadProgress.setPrefWidth(SPLASH_WIDTH - 20);
progressText = new Label("Will find friends for peanuts . . .");
splashLayout = new VBox();
splashLayout.getChildren().addAll(splash, loadProgress, progressText);
progressText.setAlignment(Pos.CENTER);
splashLayout.setStyle(
"-fx-padding: 5; " +
"-fx-background-color: cornsilk; " +
"-fx-border-width:5; " +
"-fx-border-color: " +
"linear-gradient(" +
"to bottom, " +
"chocolate, " +
"derive(chocolate, 50%)" +
");"
);
splashLayout.setEffect(new DropShadow());
}
@Override
public void start(final Stage initStage) throws Exception {
final Task<ObservableList<String>> friendTask = new Task<ObservableList<String>>() {
@Override
protected ObservableList<String> call() throws InterruptedException {
ObservableList<String> foundFriends =
FXCollections.<String>observableArrayList();
ObservableList<String> availableFriends =
FXCollections.observableArrayList(
"Fili", "Kili", "Oin", "Gloin", "Thorin",
"Dwalin", "Balin", "Bifur", "Bofur",
"Bombur", "Dori", "Nori", "Ori"
);
updateMessage("Finding friends . . .");
for (int i = 0; i < availableFriends.size(); i++) {
Thread.sleep(400);
updateProgress(i + 1, availableFriends.size());
String nextFriend = availableFriends.get(i);
foundFriends.add(nextFriend);
updateMessage("Finding friends . . . found " + nextFriend);
}
Thread.sleep(400);
updateMessage("All friends found.");
return foundFriends;
}
};
showSplash(
initStage,
friendTask,
() -> showMainStage(friendTask.valueProperty())
);
new Thread(friendTask).start();
}
private void showMainStage(
ReadOnlyObjectProperty<ObservableList<String>> friends
) {
mainStage = new Stage(StageStyle.DECORATED);
mainStage.setTitle("My Friends");
mainStage.getIcons().add(new Image(
APPLICATION_ICON
));
final ListView<String> peopleView = new ListView<>();
peopleView.itemsProperty().bind(friends);
mainStage.setScene(new Scene(peopleView));
mainStage.show();
}
private void showSplash(
final Stage initStage,
Task<?> task,
InitCompletionHandler initCompletionHandler
) {
progressText.textProperty().bind(task.messageProperty());
loadProgress.progressProperty().bind(task.progressProperty());
task.stateProperty().addListener((observableValue, oldState, newState) -> {
if (newState == Worker.State.SUCCEEDED) {
loadProgress.progressProperty().unbind();
loadProgress.setProgress(1);
initStage.toFront();
FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.2), splashLayout);
fadeSplash.setFromValue(1.0);
fadeSplash.setToValue(0.0);
fadeSplash.setOnFinished(actionEvent -> initStage.hide());
fadeSplash.play();
initCompletionHandler.complete();
} // todo add code to gracefully handle other task states.
});
Scene splashScene = new Scene(splashLayout, Color.TRANSPARENT);
final Rectangle2D bounds = Screen.getPrimary().getBounds();
initStage.setScene(splashScene);
initStage.setX(bounds.getMinX() + bounds.getWidth() / 2 - SPLASH_WIDTH / 2);
initStage.setY(bounds.getMinY() + bounds.getHeight() / 2 - SPLASH_HEIGHT / 2);
initStage.initStyle(StageStyle.TRANSPARENT);
initStage.setAlwaysOnTop(true);
initStage.show();
}
public interface InitCompletionHandler {
void complete();
}
}
@JulietteGe
Copy link

Thanks a lot! This is great, works well and looks awesome! :D Thank you for providing this code!

@MarceloAugusto
Copy link

Muito obrigado, foi muito util....
Grato.

@Perneel
Copy link

Perneel commented Mar 7, 2016

Very nice piece of code, I have been using this as a base to create my own preloader in a seperate jar. I tried to expand this to handle the download progress of the jars as well but failed to do so. If you have time, I made a question on SO about this: http://stackoverflow.com/questions/35849930/how-to-handle-java-web-start-downloading-application-in-a-preloader. Feel free to check it out!

@MICOFO
Copy link

MICOFO commented Apr 20, 2016

Very Good tutorial.
Thank you very much

@g9164313
Copy link

Good tutorial. Thank you.

@OUSSAMA-EZZIOURI
Copy link

nice one boss, I like it. Thank you soo muck :)

@tolutronics
Copy link

i will i edit it to start another window rather than list of friends

@lvwarren
Copy link

kudos, jewelsea, i have been following your threads for years on StackOverflow and they are always top notch!

@tango4567
Copy link

Wonder full tutorial. Thank you soo much

@Damian-crypto
Copy link

Great! Thank you!

@Charlie-Kwon
Copy link

Wonderful!! Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment