JavaFX全屏应用Alert弹窗层级错位、脱离父窗口显示问题咨询
JavaFX全屏Alert弹窗异常解决方案
问题1:全屏模式下新弹出Alert层级低于已有Alert
原因
Windows平台JavaFX 8~16版本存在全屏Stage所属非模态弹窗的z-order排序缺陷,后弹出的Alert即使获得焦点也不会自动触发层级重排。
解决方案
- 显式为Alert设置模态属性,推荐使用
Modality.APPLICATION_MODAL,模态弹窗会自动按弹出顺序排序层级 - 若业务需要非模态Alert,可在Alert弹出后主动调用
toFront()方法,或监听Alert的focused属性,获得焦点时自动置顶
示例修改代码(createAlert方法内新增):
// 新增模态设置 alert.initModality(Modality.APPLICATION_MODAL); // 若需要非模态则替换为下面的代码 // alert.focusedProperty().addListener((obs, oldVal, newVal) -> { // if (newVal) alert.toFront(); // });
问题2:Alert脱离父窗口单独显示
原因
默认非模态Alert未与父Stage的显示状态做绑定,Windows系统窗口切换时不会跟随父窗口最小化/隐藏。
解决方案
- 优先使用模态Alert,模态Alert默认会跟随父Stage的显示状态同步变化
- 若需要非模态Alert,可给父Stage添加
iconified(最小化)和showing属性监听,同步控制Alert的显示状态
示例修改代码(createAlert方法内新增):
// 绑定父窗口最小化状态 parentStage.iconifiedProperty().addListener((obs, oldVal, newVal) -> { alert.setIconified(newVal); }); // 绑定父窗口显示状态 parentStage.showingProperty().addListener((obs, oldVal, newVal) -> { if (!newVal) alert.hide(); });
修改后完整可运行代码
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Modality; import javafx.stage.Stage; public class Main extends Application { public static void run(String[] args) { launch(args); } @Override public void start(Stage stage) { Button button1 = new Button("CREATE 2 ALERTS"); button1.setOnAction(event -> { createAlert("First alert", stage, 300, 300); createAlert("Second alert", stage, 500, 100); }); StackPane root = new StackPane(button1); Scene scene = new Scene(root); stage.setScene(scene); stage.setFullScreen(true); stage.show(); } private void createAlert(String text, Stage parentStage, int width, int height) { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText(""); alert.setContentText(text); alert.initOwner(parentStage); // 新增模态设置 可同时解决两个问题 alert.initModality(Modality.APPLICATION_MODAL); // 非模态场景下启用以下监听代码 /* alert.focusedProperty().addListener((obs, oldVal, newVal) -> { if (newVal) alert.toFront(); }); parentStage.iconifiedProperty().addListener((obs, oldVal, newVal) -> { alert.setIconified(newVal); }); parentStage.showingProperty().addListener((obs, oldVal, newVal) -> { if (!newVal) alert.hide(); }); */ alert.getDialogPane().setPrefWidth(width); alert.getDialogPane().setPrefHeight(height); alert.show(); } }
注:以上方案在Java 8u161、Java 16对应JavaFX版本的Windows 10环境下测试通过。
内容的提问来源于stack exchange,提问作者ank
相关产品推荐
相关产品推荐

