簡體   English   中英

無法在JavaFX中更改Alert窗口的initModality

[英]Can't change initModality of an Alert window in JavaFX

在JavaFX(11)中,我試圖在主窗口上方顯示一個警告窗口,但我不希望主窗口可以被點擊。 為此,我認為我必須更改該警報窗口的initModality( https://docs.oracle.com/javafx/2/api/javafx/stage/Stage.html請參閱'模態')。 它不起作用,因為警報窗口的所有者為空?

這是我的控制器類。 主類只是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_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控制器的initialize()方法中顯示Alert ,因此在顯示主窗口之前可能正在執行代碼。 如果要在應用程序開頭顯示Alert ,則至少有兩個選項:

  1. 您的回答中調用Platform.runLater調用中的show()

    • 這樣做的缺點是它使您的代碼高度依賴於看似無關的代碼。 例如,如果由於某種原因您更改了主窗口的顯示方式和時間,則此選項可能會中斷。
  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(); } 

我通過將警報代碼放在Platform.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");
        });
    }

主窗口現在不是交互式的,就像我想要的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM