java - 无法更改 JavaFX 中警报窗口的 initModality

标签 java javafx java-11

在 JavaFX (11) 中,我试图在主窗口上方显示一个警告窗口,但我不希望主窗口可以单击。为此,我认为我必须更改该警报窗口的 initModality(https://docs.oracle.com/javafx/2/api/javafx/stage/Stage.html 参见“Modality”)。是不是因为alert window的owner为null所以不起作用?

这是我的 Controller 类。主类只是 IntelliJ IDEA 生成的默认 JavaFX 主类,而 .fxml 文件只是一个带有用于测试目的的按钮的 anchor 。

package sample;

import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.stage.Modality;

public class Controller {

    public Button button;

    public void initialize(){
        Alert alert = new Alert(Alert.AlertType.ERROR);
        System.out.println(alert.getOwner());             //output: null
        alert.initModality(Modality.APPLICATION_MODAL);
        alert.setHeight(200);
        alert.setWidth(300);
        alert.show();
        button.setOnAction(push -> System.out.println("button pressed")); //button is still pressable
    }
}

主窗口中的按钮仍然可以按下,因此 initModality 不起作用。我还尝试了 Modality.WINDOW_MODALModality.NONE,没有变化。

如果重要的话,我在 Linux 上使用 bspwm。

最佳答案

我认为问题在于窗口的显示顺序。在 Windows 10(使用 JavaFX 12.0.1)上使用以下重现问题进行测试:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        var alert = new Alert(AlertType.INFORMATION);
        alert.initModality(Modality.APPLICATION_MODAL);
        alert.setHeaderText(null);
        alert.setContentText("This is a test of application modality.");
        alert.show();

        primaryStage.setScene(new Scene(new StackPane(new Label("Hello, World!")), 500, 300));
        primaryStage.show();
    }

}

上面的结果导致对话框窗口不是正确的模态。但是,如果您将 alert.show() 移动到 primaryStage.show() 之后,一切都会按预期进行。

由于您在 FXML Controller 的 initialize() 方法中显示您的 Alert,因此很可能在您显示主窗口之前正在执行代码。如果您想在应用程序开始时显示 Alert,至少有两个选项:

  1. Platform.runLater 调用中调用 show(),就像在 your answer 中所做的那样.

    • 这样做的缺点是它使您的代码高度依赖于看似无关的代码。例如,如果出于某种原因您更改了主窗口的显示方式和时间,则此选项可能会中断。
  2. 向您的 Controller 类添加一个方法,并在显示其他窗口后调用它。

    @Override
    public void start(Stage primaryStage) throws IOException {
        FXMLLoader loader = new FXMLLoader(/*location*/);
        primaryStage.setScene(new Scene(loader.load()));
        primaryStage.show();
        loader.<Controller>getController().showMyAwesomeAlert();
    }
    

关于java - 无法更改 JavaFX 中警报窗口的 initModality,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56209941/

相关文章:

java - 在 zookeeper 中创建路径的最有效方法,其中路径的根元素可能存在也可能不存在?

java - Jenkins war 部署到 Tomcat 7

java - JDK11 HttpClient 双向 tls

java - OpenJDK 64 位服务器 VM 警告 : Archived non-system classes are disabled (resin, Ubuntu、OpenJDK 11)

java - 无法从 Fedora 30 中删除 java-11-amazon-corretto-devel

java - 哪个 java.lang.Error 后代可以安全捕获?

java - 在多线程编程中使用静态类方法

javafx - 右键单击JavaFX?

JavaFX 8 工具提示消除了舞台的透明度

java - 将 JavaFX FXML 对象组合在一起