stephan
stephan

Reputation: 271

How to make Loading Scene before application window in javaFx?

I am triying to create a loading window before real application window openning. There is a progressBar in the loading scene and it is undeterminate.

Problem is that; progressbar does not work until the real window open when i execute the program.

by the way i tried preloader class, but also not works too.

here is my code;

public class MainApp2 extends Application {


    private Stage loadingStage = new Stage();

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


    public void start(final Stage mainStage) throws Exception {

        //loading..
        loadingScreen();

        //start...
        appScreen();

    }


    private void loadingScreen() {

        ProgressBar bar = new ProgressBar(ProgressIndicator.INDETERMINATE_PROGRESS);
        bar.setPrefWidth(300);
        bar.setPrefHeight(200);

        loadingStage.initStyle(StageStyle.TRANSPARENT);
        loadingStage.initStyle(StageStyle.UNDECORATED);
        loadingStage.setScene(new Scene(bar));
        loadingStage.show();

    }


    private void appScreen() {

        new Task<Void>() {
            @Override
            protected Void call() throws Exception {

                Stage mainStage = new Stage();

                //get real window
                Scene root = new Scene(new MyAppWindow().getAppWindow());
                mainStage.setScene(root);
                mainStage.centerOnScreen();
                mainStage.show();

//                loadingStage.close();

                return null;
            }
        }.run();

    }

    public class MyAppWindow {

        public BorderPane getAppWindow(){

            System.out.println("may be initialize take a long time...");
            for (int i = 0; i < 90000000; i++) {
                System.out.print("");
            }

            return new BorderPane(new Label("Here is real application Window!"));
        }


    }


}

Upvotes: 1

Views: 3760

Answers (2)

stephan
stephan

Reputation: 271

At least I found that; there is no anyway to init a splash screen in JavaFx. Because JavaFx is managed by one thread. so I tried to this step. It works for me.

public void initAppScreen(final Stage mainStage) {

        loadingWindow = new LoadingWindow().getInitWindow();

        applicationContext = new ClassPathXmlApplicationContext("hibernate-config.xml");

        initSample();

        Platform.runLater(new Runnable() {
            public void run() {

                Scene root = new Scene(new AppWindow().getAppWindow());
                mainStage.setScene(root);

                mainStage.setTitle("My Application Title");
                mainStage.getIcons().add(new Image("/images/logo.png"));
                mainStage.setOnCloseRequest(event -> System.exit(0));

                mainStage.setWidth(APP_WINDOW_WIDTH);
                mainStage.setHeight(APP_WINDOW_HEIGHT);
                mainStage.setMinWidth(APP_WINDOW_WIDTH);
                mainStage.setMinHeight(APP_WINDOW_HEIGHT);

                Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
                mainStage.setX((screenBounds.getWidth() - APP_WINDOW_WIDTH) / 2);
                mainStage.setY((screenBounds.getHeight() - APP_WINDOW_HEIGHT) / 2);

                mainStage.show();
                loadingWindow.dispose();
            }
        });

    }

And my splash screen

public class LoadingWindow {


    public JFrame getInitWindow() {

        JFrame loadingFrame = new JFrame();

        URL url = this.getClass().getResource("/images/loading.gif");
        Icon icon = new ImageIcon(url);
        JLabel label = new JLabel(icon);

        loadingFrame.setIconImage(new ImageIcon(getClass().getResource("/images/logo.png").getPath()).getImage());
        loadingFrame.setUndecorated(true);
        loadingFrame.setBackground(new Color(0f, 0f, 0f, 0f));

        Rectangle2D screenBounds = Screen.getPrimary().getVisualBounds();
        loadingFrame.setLocation((int) ((screenBounds.getWidth() - 600) / 2), (int) ((screenBounds.getHeight() - 0) / 2));

        loadingFrame.getContentPane().add(label);
        loadingFrame.pack();
        loadingFrame.setLocationRelativeTo(null);
        loadingFrame.setVisible(true);

        return loadingFrame;
    }

}

Upvotes: 1

Sahil Manchanda
Sahil Manchanda

Reputation: 10012

You can use preloaders. here is an example. taken from source

public class FirstPreloader extends Preloader {
    ProgressBar bar;
    Stage stage;

    private Scene createPreloaderScene() {
        bar = new ProgressBar();
        BorderPane p = new BorderPane();
        p.setCenter(bar);
        return new Scene(p, 300, 150);        
    }

    public void start(Stage stage) throws Exception {
        this.stage = stage;
        stage.setScene(createPreloaderScene());        
        stage.show();
    }

    @Override
    public void handleProgressNotification(ProgressNotification pn) {
        bar.setProgress(pn.getProgress());
    }

    @Override
    public void handleStateChangeNotification(StateChangeNotification evt) {
        if (evt.getType() == StateChangeNotification.Type.BEFORE_START) {
            stage.hide();
        }
    }    
}

Upvotes: 1

Related Questions