JavaFX对话框尺寸在新版GNOME中失效的问题求助
JavaFX对话框尺寸设置在新版GNOME失效的解决方案
问题背景
JavaFX程序的Stage(对话框)尺寸、位置设置在Windows、KDE、Ubuntu 22.04旧版GNOME中正常生效,但在Ubuntu 24.04/Manjaro的新版GNOME中失效。启用OnShowing/OnShown事件处理后效果不稳定。
解决方案
问题根源是新版GNOME的Mutter窗口管理器会在窗口初始化后强制调整尺寸/位置,覆盖JavaFX的设置,以下是针对性解决方法:
1. 锁定窗口尺寸范围
先设置窗口的最小/最大尺寸为目标值,防止窗口管理器自动拉伸或缩小:
stage.setMinWidth(size); stage.setMinHeight(size); stage.setMaxWidth(size); stage.setMaxHeight(size); // 若不需要窗口可调整,直接禁用调整功能 stage.setResizable(false);
2. 延迟设置窗口参数
在窗口完全显示后,用Platform.runLater延迟执行尺寸/位置设置,确保窗口管理器的初始化操作完成后再覆盖:
stage.setOnShown(e -> { Platform.runLater(() -> { stage.setWidth(size); stage.setHeight(size); stage.setX(pos); stage.setY(pos); }); });
3. 给根节点设置最小尺寸
让Scene的根容器明确最小尺寸,避免窗口管理器根据内容自动重置窗口大小:
vBox.setMinSize(size, size);
4. 调整Stage初始化样式(可选)
如果不需要系统默认标题栏,使用UNDECORATED样式可完全规避窗口管理器的干涉;若需要标题栏,尝试UTILITY样式:
stage.initStyle(StageStyle.UTILITY);
修改后的完整代码
import javafx.application.Application; import javafx.application.Platform; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.stage.StageStyle; public class Muster extends Application { public static void main(String[] args) { launch(args); } @Override public void init() throws Exception { } @Override public void start(Stage primaryStage) { show(primaryStage, null, "Dialog 1", false, 500, 500); show(null, primaryStage, "Dialog 2", false, 400, 400); show(null, primaryStage, "Dialog 3", false, 400, 400); } private static void show(Stage primaryStage, Stage owner, String title, boolean wait, int pos, int size) { VBox vBox = new VBox(); Label lbl = new Label("Das ist ein Dialog"); Button btn = new Button("Dialog"); btn.setOnAction(a -> show(null, owner, "Wieder einer", true, 600, 600)); vBox.getChildren().add(lbl); vBox.getChildren().add(btn); vBox.setAlignment(Pos.CENTER); // 给根节点设置最小尺寸 vBox.setMinSize(size, size); try { Stage stage = primaryStage == null ? new Stage() : primaryStage; Scene scene = new Scene(vBox, size, size); stage.setScene(scene); stage.setTitle(title); if (owner != null) { stage.initOwner(owner); } // 锁定窗口尺寸范围 stage.setResizable(false); stage.setMinWidth(size); stage.setMinHeight(size); stage.setMaxWidth(size); stage.setMaxHeight(size); // 初始设置尺寸位置 stage.setWidth(size); stage.setHeight(size); stage.setX(pos); stage.setY(pos); // 窗口显示后延迟设置,覆盖GNOME的调整 stage.setOnShown(e -> { Platform.runLater(() -> { stage.setWidth(size); stage.setHeight(size); stage.setX(pos); stage.setY(pos); }); }); stage.setOnCloseRequest(e -> { System.out.println("closing width: " + stage.getWidth()); System.out.println("closing height: " + stage.getHeight()); System.out.println("closing X: " + stage.getX()); System.out.println("closing Y: " + stage.getY()); }); stage.requestFocus(); stage.toFront(); if (wait) { stage.showAndWait(); } else { stage.show(); } } catch (final Exception exc) { System.out.println(exc.getMessage()); } } }
补充说明
如果需要窗口保持可调整状态,不要设置setResizable(false),但要确保minWidth/minHeight和maxWidth/maxHeight的范围包含目标尺寸,同时保留Platform.runLater的延迟设置逻辑。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

