【问题标题】:How can I get make my program wait until JavaFX window has been closed before continuing?如何让我的程序等到 JavaFX 窗口关闭后再继续?
【发布时间】:2017-04-27 01:52:06
【问题描述】:

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

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 会立即弹出问题。如果我点击否,则图表显示,但程序结束。如果我点击是,程序会循环回到之前的对话框窗口,但在另一个对话框结束之前不会显示图表。

我想等到用户关闭条形图后再提示用户。在这一点上我很沮丧,我什至会人为地暂停一下,比如 wait(5000) 之类的,尽管我也无法让它发挥作用。

我已经阅读了很多内容,但还没有找到真正有效的解决方案。最接近的问题是:JavaFX wait till stage has been closed

从我读到的内容来看,我实际上不能让程序等待,但可以设置在窗口关闭后发生的操作。但是按照那里的建议只是导致舞台打开然后立即关闭。我已经经历过其他几个兔子洞,但都无济于事。

【问题讨论】:

  • 旁白:不要混合使用 Swing 和 JavaFX(除非你真的必须这样做)。此代码可能会在某些系统上挂起,因为您在 AWT 事件分派线程以外的线程上显示一个摆动窗口(@98​​7654325@)。请改用Alert
  • @Chris,我已经找到了您建议的主题并在发布之前尝试过。不幸的是,它没有达到我想要的效果。

标签: java javafx user-input joptionpane


【解决方案1】:

尝试使用Stage.showAndWait() 而不是Stage.show()

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

-JavaFX documentation for Stage

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

不得在主要阶段或已经可见的阶段上调用此方法。

【讨论】:

  • 同样的documentation page you linked 表示showAndWait() 方法如果在初级阶段调用会抛出IllegalStateException
  • 这实际上正是我正在寻找的东西,我因为找不到它而感到愚蠢。当这一变化如此简单时,我花了几个小时尝试许多不同的、越来越复杂的可能解决方案。感谢您的建议!对于将来看到这个的任何人,为了记录,我只是创建了另一个阶段而不是使用主阶段。 PrimaryStage 通过异常处理。
【解决方案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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-17
    • 2011-07-04
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    相关资源
    最近更新 更多