Techdroid
Techdroid

Reputation: 23

JavaFX - stage.show(); ending in program freezing

I'm trying to write a class to open an external program, make a stage that says "Please wait" with a progress indicator, wait for it to finish, then exit the stage. If I use primaryStage.showAndWait(); the program works, but if I use primaryStage.show(); the program freezes and won't continue until the class is closed. Any help would be greatly appreciated.

package application;

import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

import java.io.IOException;


public class Wait {
public static void display(String prog, String progPath){
    Stage primaryStage=new Stage();



    primaryStage.setTitle("Please Wait");
    primaryStage.setMinWidth(350);

    ProgressIndicator indicator = new ProgressIndicator();

    Label label1=new Label();
    label1.setText("Please wait for "+prog+" to finish...");


    HBox layout=new HBox(20);
    layout.getChildren().addAll(indicator, label1);
    layout.setAlignment(Pos.CENTER);
    layout.setPadding(new Insets(20,20,20,20));

    Scene scene =new Scene(layout);
    primaryStage.setScene(scene);

    primaryStage.show();// WHY U NO WORK?!?!?!?!

    try {

        Process p = Runtime.getRuntime().exec(progPath);
        p.waitFor();


    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    primaryStage.close();

}
}

Upvotes: 2

Views: 1488

Answers (1)

James_D
James_D

Reputation: 209684

Assuming Wait.display() is being executed on the FX Application Thread (which is required, since it creates and displays a Stage), your code blocks the FX Application Thread by invoking p.waitFor(). Since the FX Application Thread is blocked, it can't do any of its regular work, such as rendering the UI or responding to user input.

You need to manage the process in a background thread. Using a Task will make it easy to execute code on the FX Application Thread once the background process has finished:

public static void display(String prog, String progPath){
    Stage primaryStage=new Stage();

    primaryStage.setTitle("Please Wait");
    primaryStage.setMinWidth(350);

    ProgressIndicator indicator = new ProgressIndicator();

    Label label1=new Label();
    label1.setText("Please wait for "+prog+" to finish...");

    HBox layout=new HBox(20);
    layout.getChildren().addAll(indicator, label1);
    layout.setAlignment(Pos.CENTER);
    layout.setPadding(new Insets(20,20,20,20));

    Scene scene =new Scene(layout);
    primaryStage.setScene(scene);
    primaryStage.show();

    Task<Void> task = new Task<Void>() {
        @Override
        public Void call() throws Exception {

            try {
                Process p = Runtime.getRuntime().exec(progPath);
                p.waitFor();        
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
            return null;
    };

    task.setOnSucceeded(e -> primaryStage.close());

    Thread thread = new Thread(task);
    thread.setDaemon(true); // thread will not prevent application from exiting
    thread.start();
}

Upvotes: 3

Related Questions