0

I've just started learning JavaFX for building desktop applications and I currently don't have any personal training yet. Right now regarding the question, I'm trying to make a custom layout that depends its size to the overall size of its children. My problem is about getting the size of each child during height and width computation. Here, I'm using the getLayoutBounds() method to retrieve the children's size, but it always return 0 in my case:

@Override
protected double computePrefWidth(double height) {
  for (int i = 0; i < getChildren().size(); i++) {
    Node node = getChildren().get(i);
    System.out.println(node.getLayoutBounds().getWidth()); // returns 0
  }
}

So I guess it is about the layout pass (say, the child is not laid-out yet). But anyways, if that is the case here or not, how can I get the exact size of the node including the insets, padding, etc.? Thanks for all answers.


UPDATE

I end up using the prefWidth() and prefHeight() method which is the correct answer. It's my mistake for using the getWidth() and getHeight() method as I thought the prefWidth() method does not include paddings/insets. On the other hand, getWidth() actually rely on the layout pass, means that, it returns 0 because the nodes (children) are not laid-out yet in the stage, which is what @ᴇʟᴇvᴀтᴇ's answered below is correct.

So for the sake of others whoever come across this, you may want to read this one, and lastly, make sure all CSS stylesheets are properly applied if you are not getting expected result with the pref, min, max methods (see answers by @fabian and @SilasGyeme below).

Küroro
  • 628
  • 6
  • 20

3 Answers3

2

getWidth() returns 0 until you show the stage and layout the nodes. After that, they will have a non-zero width.

Use runLater() to run actions post layout.

Platform.runLater(() -> {
    // TODO: Calculations based on laid out sizes
});
ᴇʟᴇvᴀтᴇ
  • 12,285
  • 4
  • 43
  • 66
  • Saved my hours of searching. Thank you. I'll accept this answer asap. – Küroro May 23 '18 at 07:23
  • Problem with this one, local variable that is meant to be returned cannot be modified inside lambdas. But this is actually useful. – Küroro May 23 '18 at 10:04
2

If you implement a custom Region (or indirect subclass), it's your classes' job to determine the size of the children.

computePrefWidth ect. need to consider the size bounds of the children and determine it's own preferred size based on those values. For these kinds of calculation you should use the minWidth, minHeight, prefWidth, prefHeight, maxWidth and maxHeight methods of Node.

Example

@Override
protected double computePrefWidth(double height) {
    double size = 0;
    for (Node child : getManagedChildren()) {
        double pW = child.prefWidth(height);
        if (pW > size) {
            size = pW;
        }
    }

    // TODO: consider insets ect...
    return size;
}

The above way of determining the pref size would be suitable e.g. for something like a VBox.

Community
  • 1
  • 1
fabian
  • 80,457
  • 12
  • 86
  • 114
1

Set the setPrefWidth of the children ,then access them using getPrefWidth

sgyeme
  • 39
  • 1
  • 4