我的父节点(也就是AnchorPane,但我相信这是无关紧要的),我的对话框(基本上是其中有标题的AnchorPanes)居中的问题。
代码如下:
public void showDialog(final Dialog dialog) {
dialogStack.add(dialog);
dialogCanvas.toFront();
dialog.toFront();
dialogCanvas.setVisible(true);
dialog.setVisible(true);
getChildren().add(dialog);
dialog.widthProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if(newValue.doubleValue() > 0) {
centerDialog(dialog);
}
}
});
}
public void centerDialog(final Dialog dialog) {
double width = getWidth();
double height = getHeight();
dialog.setLayoutX(width / 2 - dialog.getWidth() / 2);
dialog.setLayoutY(height / 2 - dialog.getHeight() / 2);
}
我使用了widthProperty更改侦听器,因为你只能在渲染时将节点居中,然后才能设置宽度/高度。
当我在设置对话框的布局x / y时调试代码时,值计算得很好,但最后的对话节点位于左上角(X:0 / Y: 0)。
为什么???
我可以以某种方式触发父节点的重绘,以便元素正确定位吗?我做错了什么?
亲切的问候, 斯捷潘
答案 0 :(得分:0)
您的选择:
继续使用AnchorPane作为父级,但使用锚点约束作为
来居中AnchorPane.setTopAnchor(dialog, height / 2 - dialog.getHeight() / 2);
AnchorPane.setLeftAnchor(dialog, width / 2 - dialog.getWidth() / 2);
对父窗格的宽度和高度值的每次更改。如果希望子窗格在窗口大小调整时保持居中,则需要为宽度和高度属性添加事件侦听器。
使用Pane
代替AnchorPane作为父级,并通过setLayoutX()/ setLayoutY()对子窗格进行居中,每次更改父级的宽度和高度值(再次使用事件侦听器) 。与AnchorPane相反的Pane除了将它们调整为首选大小外,不会对其子项进行布局。
使用StackPane
代替AnchorPane作为父级,无需居中子窗格,因为StackPane会自动为您执行此操作。
使用ControlsFX对话框。
public class AnchorDemo extends Application {
private final AnchorPane anchorPaneParent = new AnchorPane();
private final AnchorPane anchorPaneChild = new AnchorPane(new Label("TEXT TEXT TEXT TEXT TEXT"));
@Override
public void start(Stage primaryStage) {
anchorPaneParent.setStyle("-fx-border-color:red");
anchorPaneChild.setStyle("-fx-border-color:green");
anchorPaneParent.getChildren().add(anchorPaneChild);
anchorPaneParent.layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
@Override
public void changed(ObservableValue<? extends Bounds> arg0, Bounds oldBound, Bounds newBound) {
System.out.println("oldBound = " + oldBound);
System.out.println("newBound = " + newBound);
System.out.println("");
if (oldBound.getHeight() != newBound.getHeight() || oldBound.getWidth() != newBound.getWidth()) {
updateChildAnchorConstraint();
}
}
});
Scene scene = new Scene(anchorPaneParent, 300, 250);
primaryStage.setScene(scene);
primaryStage.show();
updateChildAnchorConstraint();
}
private void updateChildAnchorConstraint() {
AnchorPane.setTopAnchor(anchorPaneChild, anchorPaneParent.getHeight() / 2 - anchorPaneChild.getHeight() / 2);
AnchorPane.setLeftAnchor(anchorPaneChild, anchorPaneParent.getWidth() / 2 - anchorPaneChild.getWidth() / 2);
}
public static void main(String[] args) {
launch(args);
}
}
答案 1 :(得分:0)
问题是这一切都是在单线程中完成的,有关布局的信息还不知道......但是使用Platform.runLater(...)我能够解决问题。
当你知道如何解决它时,它会非常优雅......
public void showDialog(final Dialog dialog) {
dialogStack.add(dialog);
dialogCanvas.toFront();
dialog.toFront();
dialogCanvas.setVisible(true);
dialog.setVisible(true);
getChildren().add(dialog);
dialog.widthProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
if(newValue.doubleValue() > 0) {
centerDialog(dialog);
}
}
});
}
public void centerDialog(final Dialog dialog) {
Platform.runLater(new Runnable() {
@Override
public void run() {
double width = getWidth();
double height = getHeight();
dialog.setLayoutX(width / 2 - dialog.getWidth() / 2);
dialog.setLayoutY(height / 2 - dialog.getHeight() / 2);
}
});
}