How to get the height or prefer height of a node in JavaFX, I have 3 VBox
and I want to add nodes to the the most freer panel, example:
Childrens Total Height of the children's(Sum)
VBoxA 5 890
VBoxB 4 610
VBoxC 2 720
in this case, the most freer is the VBoxB
, I calculate the most freer pane with this method:
private int getFreerColumnIndex() {
if(columns.isEmpty())
return -1;
int columnIndex = 0;
int minHeight = 0;
for(int i = 0; i < columns.size(); i++) {
int height = 0;
for(Node n : columns.get(i).getChildren()) {
height += n.getBoundsInLocal().getHeight();
}
if(i == 0) {
minHeight = height;
} else if(height < minHeight) {
minHeight = height;
columnIndex = i;
}
if(height == 0)
break;
}
return columnIndex;
}
This method only works if I add 1 element at the time. But if I add more elements at the time:
for (int i = 0; i < 10; i++) {
SomeNode r1 = new SomeNode ();
myPane.addElement(r1);
}
the method getFreerColumnIndex
return the same index. This is because the new nodes dont have heigth in local yet.
So this line:
height += n.getBoundsInLocal().getHeight();
will return 0
with the new nodes.
Anyone knows how to get the heigth of a node ?
Extra:
SomeNode
extends of Node
Method addElement() at myPane:
public void addElement(final Node element) {
index = getFreerColumnIndex();
columns.get(index).getChildren().add(element);
}
Extra 2:
suppose we have 3 vbox: Before:
A B C
| | |
| |
|
Run:
for (int i = 0; i < 10; i++) {
SomeNode r1 = new SomeNode ();
myPane.addElement(r1);
}
After:
A B C
| | |
| | |
| |
|
|
|
|
|
|
|
|
Correct:
A B C
| | |
| | |
| | |
| | |
| | |
|
|
= Some node
What you need to do is:
applyCss()
andlayout()
on each of the nodes (or the dummy scene root).Related
To find out how to measure the size of a node, see the answer to:
Background
JavaFX layout calculations work by applying CSS and a layout pass. Normally this occurs as part of a pulse (a kind of automated 60fps tick in the internal JavaFX system which checks for any dirty objects in the scene which need new css or layout applied to them). In most cases, you can just specify the changes you want to the scene and let the automated pulse layout mechanism handle the layout at that time; doing so is quite efficient as it means that any changes between a pulse are batched up and you don't need to manually trigger layout passes. However, when you need to actually get the size of things before the layout occurs (as in your case), then you need to manually trigger the CSS application and layout pass before you try to query the height and width extents of the node.
Documentation
Unfortunately the detailed Java 8u20 Javadoc for the
node.applyCSS()
method is currently broken, so I'll reproduce the sample which is in the Javadoc code here, so you can see the recommended usage in context. For the next Java feature release (8u40), the broken javadoc is fixed as part of RT-38330 Javadoc is missing for several methods of the Node class, so with that release, you will be able to find the following text in the JavaFX javadoc:Alternative
The other option here is to override the
layoutChildren()
method of a parent node, which is "Invoked during the layout pass to layout the children in this Parent.". In doing so, it may also be necessary to override methods tocomputePrefHeight()
as well as other computation methods for prefWidth and min & max height & width. A detailed description of using this approach is complicated and outside the scope of this answer.