How to show main stage after splash screen


Question

I want to modify this code:

public class test extends Application
{

    private Pane splashLayout;
    private ProgressBar loadProgress;
    private Label progressText;
    private Stage mainStage;
    private static final int SPLASH_WIDTH = 600;
    private static final int SPLASH_HEIGHT = 200;

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

    @Override
    public void init()
    {
        ImageView splash = new ImageView(getClass().getResource("/images/splash.png").toExternalForm());
        loadProgress = new ProgressBar();
        loadProgress.setPrefWidth(SPLASH_WIDTH + 20);
        progressText = new Label("All modules are loaded.");
        splashLayout = new VBox();
        splashLayout.getChildren().addAll(splash, loadProgress, progressText);
        progressText.setAlignment(Pos.CENTER);
        splashLayout.setEffect(new DropShadow());
    }

    @Override
    public void start(final Stage initStage) throws Exception
    {
        final Task<ObservableList<String>> friendTask = new Task()
        {
            @Override
            protected ObservableList<String> call() throws InterruptedException
            {
                ObservableList<String> foundFriends =
                        FXCollections.<String>observableArrayList();
                ObservableList<String> availableFriends =
                        FXCollections.observableArrayList("Network Module", "User Module", "User Interface", "User Controls");

                updateMessage("Loading Modules . . .");
                for (int i = 0; i < availableFriends.size(); i++)
                {
                    Thread.sleep(900);
                    updateProgress(i + 1, availableFriends.size());
                    String nextFriend = availableFriends.get(i);
                    foundFriends.add(nextFriend);
                    updateMessage("Loading Modules . . . Loading " + nextFriend);
                }
                Thread.sleep(500);
                updateMessage("All Modules are loaded.");

                return foundFriends;
            }
        };

        showSplash(initStage, friendTask);
        new Thread(friendTask).start();
        showMainStage(friendTask.valueProperty());
    }

    private void showMainStage(ReadOnlyObjectProperty<ObservableList<String>> friends)
    {
        mainStage = new Stage(StageStyle.DECORATED);
        mainStage.setTitle("Loading Modules");
        //mainStage.setIconified(true);
        //mainStage.getIcons().add(new Image("http://cdn1.iconfinder.com/data/icons/Copenhagen/PNG/32/people.png"));
        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)
    {
        progressText.textProperty().bind(task.messageProperty());
        loadProgress.progressProperty().bind(task.progressProperty());
        task.stateProperty().addListener(new ChangeListener<Worker.State>()
        {
            @Override
            public void changed(ObservableValue<? extends Worker.State> observableValue, Worker.State oldState, Worker.State newState)
            {
                if (newState == Worker.State.SUCCEEDED)
                {
                    loadProgress.progressProperty().unbind();
                    loadProgress.setProgress(1);
                    mainStage.setIconified(false);
                    initStage.toFront();
                    FadeTransition fadeSplash = new FadeTransition(Duration.seconds(1.2), splashLayout);
                    fadeSplash.setFromValue(1.0);
                    fadeSplash.setToValue(0.0);
                    fadeSplash.setOnFinished(new EventHandler<ActionEvent>()
                    {
                        @Override
                        public void handle(ActionEvent actionEvent)
                        {
                            initStage.hide();
                        }
                    });
                    fadeSplash.play();
                } // todo add code to gracefully handle other task states.
            }
        });
        Scene splashScene = new Scene(splashLayout);
        initStage.initStyle(StageStyle.UNDECORATED);
        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.show();
    }
}

Can you tell me how I can modify the code to display the main stage when the splash screen finishes loading? In this example the main stage and the splash screen are displayed simultaneously.

Also do you know any good examples of splash screens?

1
1
6/8/2013 6:56:36 PM

Are you familiar with JavaFX preloaders? They might be a better approach for at least what you are doing in that sample: http://docs.oracle.com/javafx/2/deployment/preloaders.htm

As for 'switching stages' when your task is done (i may be missing the point here): Why not add the following before the return statement:

Platform.runLater(new Runnable(){
    public void run() {
        initStage.close();
        showMainStage(foundFriends);
    }
}

Arguably, passing the tasks result directly in this fashion would be simpler that having your main view's UI bound to the thread's value property, wouldn't it?

3
6/9/2013 10:12:31 AM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon