Richard, Is there a sequence diagram (or similar) where the layout process is described in detail? It’s hard to in text get a clear and precise view on how the layout process in the Node hierarchy is happening.
The sequence diagram would be good to have as a constraint for building layout panes. Otherwise its easy to time things incorrectly with strange layout artefacts as a result. It’s especially important for devs to know which methods are called for the pre-layout (size measuring) phase and them for the actual layout phase. Cheers, Mikael On 28 Jul 2014, at 07:38, Martin Sladecek <martin.slade...@oracle.com> wrote: > The super.layoutChildren should size every child of the control (which is > VBox), but not child's children. The control must finish the layout before > children can do theirs. If you need to do layout on some child before that, > you can call .layout() on it. It will do it's layout using it's current size. > You should have all the bounds correct after that call. > > But that would not work in your case anyway. You have both childs in a HBox, > which takes care of resizing the children. This means you need to layout the > HBox to get children size and in order to do that, you need HBox to be at > it's final size, which will happen during the VBox layout. So your steps > would be: > 1) super.layoutChildren() - VBox is resized to Controls content size > 2) now the VBox is resized, you can call vbox.layout() > 3) now HBox is resized, so call hbox.layout() > 4) children are resized. They have correct layout bounds now. But in order to > get correct boundsInParent (but maybe you really need layout bounds?), you > need to call .layout() on children too. > > Even if you do all these steps, calling setPrefWidth() on child2 marks the > whole tree dirty again. Because HBox needs to resize child2 using it's new > PrefWidth. This also means, HBox prefwidth will be different, so it's parent > (VBox) must do the same. Ditto with the control. Also, the HBox (VBox, > control) may not have enough size to resize child2 to it's pref width, so > child1 might be shrinked as a result, which breaks your invariant. You are > basically changing the input for HBox's layout (child2.pref size) based on > it's output (child1 size), which makes this a loop. > > So in order to really make this work, you need to manage the child nodes > directly and compute your layout by yourself. This can be done either by > using your own subclass of Pane and overriding it's layoutChildren. Or if you > want to do everything in Skin's layoutChildren, you can make the children > unmanaged, but then it doesn't really matter where they are in the > scenegraph, HBox won't be managing them. > > Hope this helps! > > -Martin > > > On 25.7.2014 18:56, Richard Bair wrote: >> Hmmm. The first question I have is whether boundsInParent is really what you >> want to use, vs. layout bounds. But assuming it is what you want, why are >> the bounds zero? This is during the layout pass, which is the right place to >> be doing what you’re doing. The super layoutChildren call will size >> everything based on the contentX, contentY, contentWidth, contentHeight >> (http://hg.openjdk.java.net/openjfx/8u-dev/rt/file/4b8d06211312/modules/controls/src/main/java/javafx/scene/control/SkinBase.java). >> Is it possible that the parent itself is size 0? boundsInParent should >> always be invalidated automatically whenever the width/height/transforms/etc >> changes. If not that is definitely a bug (that you can write a simple test >> case for to prove). >> >> But my first guess is maybe the parent is size 0 as well, due to something >> else (maybe the pref size of the control is 0 to start with or something…) >> >> Richard >> >> On Jul 24, 2014, at 3:34 AM, Werner Lehmann <lehm...@media-interactive.de> >> wrote: >> >>> Hi, >>> >>> inside a control skin I have the following code pattern: >>> >>> protected void layoutChildren(...) >>> { >>> super.layoutChildren(...); >>> >>> Node child1 = ... >>> Bounds bip = child1.getBoundsInParent(); >>> >>> if (!animating) { >>> Node child2 = ... >>> child2.setTranslateX(bip.getMinX(); >>> child2.setPrefWidth(bip.getWidth()); >>> } >>> } >>> >>> The skin scene graph looks roughly like this: >>> >>> VBox >>> HBox { ..., child1, ...} >>> child2 >>> ... >>> >>> Everything is layouted just fine but I want to adjust child2.translateX and >>> prefWidth based child1 bounds. This does not work initially because >>> boundsInParent returns zero components leading to incorrect initial display >>> of the control. >>> >>> Seems as if boundsInParent is not yet updated. I guess I could use a >>> binding for that but it would conflict with an animation I also have on >>> translateX and prefWidth. >>> >>> Maybe there is a better time to make those adjustments on child2? >>> >>> Rgds >>> Werner >