Mansueli
Mansueli

Reputation: 6939

Close Stage in JavaFx from task

I am trying to close a Stage in JavaFX from a task (thread).

In order to accomplish this, I tried to pass the references to the Stage to the a class that extends Task, setting the current Stage there.

Then closing the Stage when the call() is over. But .close() and .hide() didn't hide/close the Stage at all.

Class: SampleStage

public class SampleStage extends Application {
    @Override
    public void start(final Stage primaryStage) throws Exception {
        primaryStage.setTitle("JavaFx Dialog");
        final Button btn = new Button();
        btn.setText("Click me to display popup dialog");
        btn.setOnAction(new EventHandler<ActionEvent>() {
            @Override public void handle(ActionEvent e) {
                Stage dialog = new Stage();
                Taskee task = new Taskee();
                dialog.initStyle(StageStyle.UTILITY);
                task.setStage(dialog);
                new Thread(task).start();
                Scene scene2 = new Scene(new Group(new Text(25, 25, "Hello World!")));
                dialog.setScene(scene2);
                dialog.show();
            }
        });
        StackPane root = new StackPane();
        root.getChildren().add(btn);
        primaryStage.setScene(new Scene(root, 300, 250));
        primaryStage.show();

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

Class Taskee:

import javafx.concurrent.Task; import javafx.stage.Stage;

public class Taskee extends Task<Void>{
    private Stage stage;
    @Override
    protected Void call() throws Exception {
        for(int i=0;i<10;i++){
            //@DoSomething()
            for(long l=0;l<10000;l++);
            System.out.println("i=" + i);
        }
        getStage().close();
        getStage().hide();
        return null;
    }
    public Stage getStage() {
        return stage;
    }
    public void setStage(Stage stage) {
        this.stage = stage;
    }
}

Note: getStage().getScene().getWindow().hide(); doesn't work either.

Upvotes: 1

Views: 1635

Answers (1)

James_D
James_D

Reputation: 209330

The hide() method must be called on the FX Application thread. (In Java 8, your code would actually throw an exception.)

Use the Task's setOnSucceeded() handler to close the stage in a situation like this:

public class Taskee extends Task<Void>{

    private Stage stage;

    public Taskee() {
        setOnSucceeded(new EventHandler<WorkerStateEvent>() {
            @Override
            public void handle(WorkerStateEvent event) {
                if (stage != null) {
                    stage.hide();
                }
            }
        });
    }
    @Override
    protected Void call() throws Exception {
        for(int i=0;i<10;i++){
            //@DoSomething()
            for(long l=0;l<10000;l++);
            System.out.println("i=" + i);
        }
        return null;
    }
    public Stage getStage() {
        return stage;
    }
    public void setStage(Stage stage) {
        this.stage = stage;
    }
}

Upvotes: 2

Related Questions