More about bounds and positioning nodes

On my last post about bounds titled “Bounds in Java”, I introduced the different types of bounds available in JavaFx and what bounds are. This post is centered towards when to use those bounds and a simple trick to center your node in the screen. Just a quick review, bounds in JavaFx can be accessed in three different ways i.e. accessing  the layoutBounds, boundsInLocal, and boundsInParent of the nodes.  At first I really didn’t like the idea of having three different way to access the bounds and it was more confusing to me coming from a Java Swing background. However, now I think of it, I agree that it is a neat idea and gives the programmer more control and flexibility towards designing the UI. The best and easy way for me to figure out when to use which bounds is to remember this:

layoutBounds :- node


boundsInParent:node +effect/clip + transformations(transform/scale/translations)

So we decide which bound variables we want to use looking at how we want the node to be displayed. Lets suppose I have a ImageView node with reflection effect and rotate(45 degrees) effect applied on it (i will provide the code below). Now, I use the layoutBounds variables if I just want to center the node in the screen. Keep in mind using layout bounds will just center the node (i.e. the image without the reflection part is centered and the reflection is positioned respectively after the node is centered). If I want to center the node along with the reflection of the node (i.e. center the whole image + its reflection) then I use the boundsInLocal variables. The case of boundsInParent is a bit unexplainable because it did not work as I thought it was supposed to be. I applied a rotate transform effect and then tried to center the node along with the reflection and the rotate effect using the boundsinParent variables but the result was not as what i expected. My guess is that boundsInParent comes in handy if we are messing around with groups. Anyways, boundsInParent and boundsInLocal are not recommended to be used.

QuickTip on how to position nodes at the center of the screen:

nodes can be positions at the center of the screen using this formula:

translateX/layoutX/x = (width of screen – width of node)/2;

translateY/layoutY/y = (height of screen – height of node)/2;

We can get the width and height of the node using layoutBounds, BoundsInLocal and BoundsinParent variables. Like i said above, if we use laoyoutBounds then only the node without its effect and transform will be centered, and if we use BoundsInLocal then the node along with the effect will be centered. BoundsInParent case was not as expected so I still need to do more research on it (or someone please explain me).

Here is the example I ran:

var test: ImageView = ImageView
     image: Image
       url: "{__DIR__}Images/a10.jpg" //change this url to point to an image in your folder

       fraction: 0.75
       topOffset: 0.0
       topOpacity: 0.5
       bottomOpacity: 0.0

     rotate: 45

     //centers image only and then reflection is applied.
     translateX: bind (stage.scene.width - test.layoutBounds.width)/2;
     translateY: bind (stage.scene.height - test.layoutBounds.height)/2;

    //uncomment this one to see the boundsInLocal in action. this will center the image along with the reflection effect.
    translateX: bind (stage.scene.width - test.boundsInLocal.width)/2;
    translateY: bind (stage.scene.height - test.boundsInLocal.height)/2;
    //uncomment this one to see the boundsInParent in action. creates unexpected result in my case.
   //Please shine some light on this one to me.
   translateX: bind (stage.scene.width - test.boundsInParent.width)/2;
   translateY: bind (stage.scene.height - test.boundsInParent.height)/2;


Below is the result of using layoutBounds, BoundsInLocal and BoundsInParent from left to right respectively on an imageview. We can clearly see that layoutBounds center the image only, BoundsInLocal center the image along with the reflection effect, and BoundsInParent is not even rotating right.(Explain!!!)

layoutBounds, BoundsInLocal, BoundsInParent