それを起動したボタンなどの近くにダイアログを表示する
import javafx.beans.property.*; import javafx.geometry.*; import javafx.scene.*; import javafx.scene.control.*; import javafx.stage.*; public abstract class RelocateAroundNode { public static class ForStage extends RelocateAroundNode { private Stage stage; public ForStage(Node node, Stage stage) { super(node, stage.widthProperty(), stage.heightProperty()); this.stage = stage; if (stage.isShowing()) { relocateWindow(); return; } } protected void setX(double x) { stage.setX(x); } protected void setY(double y) { stage.setY(y); } } public static class ForDialog extends RelocateAroundNode { private Dialog<?> dialog; public ForDialog(Node node, Dialog<?> stage) { super(node, stage.widthProperty(), stage.heightProperty()); this.dialog = stage; if (stage.isShowing()) { relocateWindow(); return; } } protected void setX(double x) { dialog.setX(x); } protected void setY(double y) { dialog.setY(y); } } private Node node; private ReadOnlyDoubleProperty windowWidthProperty; private ReadOnlyDoubleProperty windowHeightProperty; protected abstract void setX(double x); protected abstract void setY(double y); protected RelocateAroundNode(Node node, ReadOnlyDoubleProperty width, ReadOnlyDoubleProperty height) { this.node = node; this.windowWidthProperty = width; this.windowHeightProperty = height; width.addListener((o, ol, ne)-> windowSizeChanged()); height.addListener((o, ol, ne)-> windowSizeChanged()); } protected void windowSizeChanged() { if (Double.isNaN(windowWidthProperty.get())) return; if (Double.isNaN(windowHeightProperty.get())) return; relocateWindow(); } protected void relocateWindow() { getScreenSize(); double windowWidth = windowWidthProperty.get(); double windowHeight = windowHeightProperty.get(); Bounds nodeB = node.localToScreen(node.getBoundsInLocal()); double nodeCenterX = (nodeB.getMinX() + nodeB.getMaxX()) / 2; double nodeCenterY = (nodeB.getMinY() + nodeB.getMaxY()) / 2; double windowNewX = nodeCenterX - windowWidth / 2; double windowNewY = nodeCenterY - windowHeight / 2; windowNewX = Math.max(0, windowNewX); windowNewX = Math.min(windowNewX, screenWidth - windowWidth); windowNewY = Math.max(0, windowNewY); windowNewY = Math.min(windowNewY, screenHeight - windowHeight); setX(windowNewX); setY(windowNewY); } private static void getScreenSize() { if (vb == null) { vb = Screen.getPrimary().getVisualBounds(); screenWidth = vb.getWidth(); screenHeight = vb.getHeight(); } } private static Rectangle2D vb; private static double screenWidth; private static double screenHeight; }
以下のように使用する。
Alert alert = new Alert(AlertType.WARNING, "ok?", ButtonType.OK, ButtonType.CANCEL); alert.initOwner(button.getScene().getWindow()); new RelocateAroundNode.ForDialog(button, alert); alert.showAndWait();