How can I get make my program wait until JavaFX window has been closed before continuing?

12,550

Solution 1

Try using Stage.showAndWait() instead of Stage.show().

The show() method returns immediately regardless of the modality of the stage. Use the showAndWait() method if you need to block the caller until the modal stage is hidden (closed). The modality must be initialized before the stage is made visible.

- JavaFX documentation for Stage

As James_D points out, you'll need to create another stage first, as using this on the primary stage will cause an error.

This method must not be called on the primary stage or on a stage that is already visible.

Solution 2

Like all UI toolkits, JavaFX is event driven. This means that you typically do not write code to loop through UI tasks, but write event handlers that respond to user events (including closing a window). This is essentially what you correctly summarized in your question:

From what I read there is that I can't actually cause the program to wait, but can set actions to occur once the window is closed.

You should approach this by creating an alert (don't use a Swing JOptionPane in a JavaFX application), and registering onHidden listeners with both the primary stage and the alert. The onHidden handler for the primary stage will show the alert. The onHidden handler for the alert will show the primary stage (perhaps resetting some data first) if the user chooses "Yes". Something like:

Scene scene = BarGraph.getBarChart();
primaryStage.setScene(scene);
primaryStage.setTitle("Bar Chart");

Alert alert = new Alert(AlertType.CONFIRMATION);
alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO);
alert.setContentText("Would you like to enter another number?");

// when alert closes, if user chose "YES", reshow the primary stage:
alert.setOnHidden(e -> {
    if (alert.getResult() == ButtonType.YES) {
        primaryStage.show();
    }
});

// when the primary stage is closed, show the alert asking if the user 
// wants to show another chart:
primaryStage.setOnHidden(e -> alert.show());

primaryStage.show();

Here's a simplified (i.e. no Bar Chart), but complete, example:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ReshowStageAlert extends Application {

    @Override
    public void start(Stage primaryStage) {

        VBox root = new VBox(5, new Label("Enter a number"), new TextField());
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root, 400, 400);
        primaryStage.setScene(scene);

        Alert alert = new Alert(AlertType.CONFIRMATION);
        alert.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO);
        alert.setContentText("Would you like to enter another number?");
        alert.setOnHidden(e -> {
            if (alert.getResult() == ButtonType.YES) {
                primaryStage.show();
            }
        });
        primaryStage.setOnHidden(e -> alert.show());

        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Share:
12,550
Crislips
Author by

Crislips

Updated on June 19, 2022

Comments

  • Crislips
    Crislips almost 2 years

    I have a program that is displaying a barchart of results. I want to wait until the user closes the bar chart to continue to the next line of code which is asking if they want to enter new information for the chart.

    Scene scene = BarGraph.getBarChart();
    primaryStage.setScene(scene);
    primaryStage.setTitle("Bar Chart");
    primaryStage.show();
    
    repeat = JOptionPane.showConfirmDialog(null, "Would you like to enter another number?");
    

    What is happening is the scene for the bar chart will open, but nothing will be displayed and immediately JOptionPane pops up with the question. If I hit no, then the chart displays, but the program ends. If I hit yes, the program loops back to earlier dialog windows, but won't display the chart until the other dialog ends.

    I want to wait to prompt the user until after they close the bar chart. I'm so frustrated at this point, that I'd even put an artificial pause like wait(5000) or something, though I have not been able to get that to work either.

    I've read into this so much and have yet to find a solution that actually works. The closest question was this: JavaFX wait till stage has been closed

    From what I read there is that I can't actually cause the program to wait, but can set actions to occur once the window is closed. But following the suggestions there just caused the stage to open and then immediately close. I've been down several other rabbit holes, but to no avail.