Can';t更改JavaFX中警报窗口的初始模式

Can';t更改JavaFX中警报窗口的初始模式,java,javafx,java-11,Java,Javafx,Java 11,在JavaFX(11)中,我试图在主窗口上方显示一个警报窗口,但我不希望主窗口可以单击。要做到这一点,我认为我必须更改该警报窗口的初始模式(请参阅“模式”)。它是否因为警报窗口的所有者为空而不起作用 这是我的控制器类。main类只是IntelliJ IDEA生成的默认JavaFX主类,.fxml文件只是一个带有按钮的锚机,用于测试 package sample; import javafx.scene.control.Alert; import javafx.scene.control.But

在JavaFX(11)中,我试图在主窗口上方显示一个警报窗口,但我不希望主窗口可以单击。要做到这一点,我认为我必须更改该警报窗口的初始模式(请参阅“模式”)。它是否因为警报窗口的所有者为空而不起作用

这是我的控制器类。main类只是IntelliJ IDEA生成的默认JavaFX主类,.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无法工作。我还尝试了
模态.WINDOW\u模态
模态。无
,无变化


如果有必要的话,我使用bspwm在Linux上运行。

我通过将警报代码放入
平台来修复它。runLater()
方法如下:

public void initialize(){
        Alert alert = new Alert(Alert.AlertType.ERROR);    
        alert.initModality(Modality.APPLICATION_MODAL);
        alert.setHeight(200);
        alert.setWidth(300);

        Platform.runLater(alert::show());

        button.setOnAction(push -> {
            System.out.println("button pressed");
        });
    }

主窗口现在不是交互式的,正如我所希望的。

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

上面的结果是对话框窗口不是正确的模态。但是,如果将
alert.show()
移动到
primaryStage.show()
之后,一切都会正常工作

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

  • 平台内调用
    show()
    。稍后运行
    调用,就像在中一样

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

    @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();
    }
    
    @覆盖
    公共无效开始(阶段primaryStage)引发IOException{
    FXMLLoader=新的FXMLLoader(/*位置*/);
    setScene(新场景(loader.load());
    primaryStage.show();
    loader.getController().showMyAwesomeAlert();
    }
    

  • 我想这是因为您的
    警报最终显示在另一个窗口之前。这是因为我在initialize()方法中运行了代码吗?如何确保警报窗口在应用程序启动后立即打开?谢谢,我将使用第二个选项。
    
    @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();
    }