无法更改JavaFX中的Alert窗口的initModality

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

这是我的控制器类.主类只是由IntelliJ IDEA生成的默认JavaFX Main类,.fxml文件只是一个带有按钮的锚定窗格,用于测试.

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_MODAL和Modality.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控制器的initialize()方法中显示Alert的,因此在显示主窗口之前,代码可能正在执行.如果要在应用程序开始时立即显示警报,则至少有两个选项:

>在Platform.runLater调用中调用show(),就像在your answer中一样.

>这样做的缺点是它使您的代码高度依赖看似无关的代码.例如,如果出于任何原因更改了显示主窗口的方式和时间,则此选项可能会中断.

>将方法添加到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();
}
上一篇:如何使用Maven构建可运行的JavaFX应用程序?


下一篇:JavaFX脚本和Visage是否等效?