JavaFX未将节点定位在父节点中

时间:2014-05-08 07:52:38

标签: javafx

我的父节点(也就是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)。

为什么???

我可以以某种方式触发父节点的重绘,以便元素正确定位吗?我做错了什么?

亲切的问候, 斯捷潘

2 个答案:

答案 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);
        }
    });

}