如何让我的程序等到JavaFX窗口关闭后再继续?

时间:2017-04-27 01:52:07

标签: java javafx user-input joptionpane

我有一个显示结果条形图的程序。我想等到用户关闭条形图以继续下一行代码,询问他们是否要输入图表的新信息。

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

repeat = JOptionPane.showConfirmDialog(null, "Would you like to enter another number?");

正在发生的事情是条形图的场景将会打开,但不显示任何内容,并立即弹出JOptionPane问题。如果我没有,则显示图表,但程序结束。如果我点击是,程序将循环回到之前的对话框窗口,但不会显示图表,直到另一个对话框结束。

我想等到用户关闭条形图之后再等它。我在这一点上非常沮丧,我甚至做了一个人为的停顿,比如等待(5000)或其他什么,虽然我也无法让它工作。

我已经读了这么多,还没有找到真正有用的解决方案。最接近的问题是:JavaFX wait till stage has been closed

从我读到的内容中,我实际上无法让程序等待,但可以在窗口关闭后设置动作。但是根据这些建议,只是让舞台开启然后立即关闭。我已经在其他几个兔子洞里摔倒,但无济于事。

2 个答案:

答案 0 :(得分:3)

尝试使用Stage.showAndWait()代替Stage.show()

  

无论阶段的形式如何,show()方法都会立即返回。如果需要阻止调用者直到隐藏(关闭)模态阶段,请使用showAndWait()方法。必须在阶段可见之前初始化模态。

     

- JavaFX documentation for Stage

As James_D points out,您需要先创建另一个阶段,因为在主阶段使用此阶段会导致错误。

  

不得在主舞台或已经可见的舞台上调用此方法。

答案 1 :(得分:2)

与所有UI工具包一样,JavaFX是事件驱动的。这意味着您通常不会编写代码来循环执行UI任务,而是编写响应用户事件的事件处理程序(包括关闭窗口)。这基本上是您在问题中正确总结的内容:

  

从我读到的内容中,我实际上无法使程序等待,但可以在窗口关闭后设置动作。

您应该通过创建警报(不要在JavaFX应用程序中使用Swing JOptionPane)并向主要阶段和警报注册onHidden侦听器来解决此问题。主阶段的onHidden处理程序将显示警报。如果用户选择“是”,则警报的onHidden处理程序将显示主要阶段(可能首先重置某些数据)。类似的东西:

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();

这是一个简化的(即没有条形图),但是完整的例子:

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);
    }
}