Saturday 18 September 2010

How to position nodes using layoutInfo?

Hi guys,
Hope you all are doing ok. Today I’d like to describe another method of positioning nodes within a container. This time we will have a look at the layoutInfo variable and LayoutInfo class. Mentioned variable is accessible in any node in javafx. To be more specific layoutInfo is inherited from the “big daddy” Node class. The information stored in layoutInfo tell the container how to position the particular node within its bounds. Objects of LayoutInfo are used to describe what exactly we want to do with the node to position.

Before reading further it would be a great idea if you checked LayoutInfo class description in javafxdoc:



As always let’s have a look at the example:



From the picture above you can see that the application consists of two red rectangles one positioned in top left corner and the other in bottom right corner. They are exactly half of the width and height of the window. They also connected in the exact middle.  In addition, when we resize the window they keep the proportion:



I hope you more or less understand what the application does. The next step is to have a look at the code for this example:

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Stack;
import javafx.geometry.VPos;
import javafx.geometry.HPos;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.layout.LayoutInfo;

var scene: Scene;

Stage {
    title: "Stack and LayoutInfo"
    scene: scene = Scene {
        width: 200
        height: 200
        content: [

            Stack {
                height: bind scene.height;
                width: bind scene.width;
                content: [

                    Rectangle {
                        width: bind scene.width / 2
                        height: bind scene.height / 2
                        fill: Color.RED;

                        layoutInfo: LayoutInfo {
                            vpos: VPos.TOP
                            hpos: HPos.LEFT
                        } // end LayoutInfo
                    } // end Rectangle

                    Rectangle {
                        width: bind scene.width / 2
                        height: bind scene.height / 2
                        fill: Color.RED;

                        layoutInfo: LayoutInfo {
                            vpos: VPos.BOTTOM
                            hpos: HPos.RIGHT
                        } // end LayoutInfo
                    } // end Rectangle
                ] // end Stack content
            } // end Stack
        ] // end Scene content
    } // end Scene
} // end Stage

From the listing above you can see that as a container I used Stack (discussed in previous post). I did it from one reason. Stack centres all of the nodes by default. It gives me perfect opportunity to demonstrate the power of layoutInfo. If we didn’t use this variable the application would look as follows:


I would also like you too notice that the height and width is calculated using bind statement. It assures that the rectangle will have half of the scene's height and width. 

Let’s concentrate on the one of the rectangles (one in top left corner):

Rectangle {
width: bind scene.width / 2
height: bind scene.height / 2
fill: Color.RED;

layoutInfo: LayoutInfo {
vpos: VPos.TOP
hpos: HPos.LEFT
} // end LayoutInfo
} // end Rectangle

In here you can see the variable layoutInfo with object of LayoutInfo class assigned to it. This class consists of many variables, which allow container to manipulate the node. The ones seen above are:

vpos – sets the vertical position of the node (in this example top). Expects constant value from VPos     class.
hpos – sets horizontal position of the node(in this example left). Expects constant value from HPos class.

In order to assign proper values we need to import two library classes:

javafx.geometry.VPos
javafx.geometry.HPos

Possible constant values for HPos ( from JavaFX API documentation ):

CENTER - Indicates centered horizontal position
LEADING - Indicates leading horizontal position, which means left in left-to-right context and right in a right-to-left context.
LEFT - Indicates left horizontal position.
RIGHT - Indicates left horizontal position.
TRAILING - Indicates trailing horizontal position, which means right in left-to-right context and left in a right-to-left context

On the other hand VPos provides following constants:

BASELINE - Indicates baseline vertical position.
BOTTOM - Indicates bottom vertical position.
CENTER - Indicates centered vertical position.
PAGE_END - Indicates vertical position at the end of the page, which means bottom in a top-to-bottom context and top in a bottom-to-top context.
PAGE_START - Indicates vertical position at the start of the page, which means top in a top-to-bottom context and bottom in a bottom-to-top context.
TOP - Indicates top vertical position.

Using these two variables gives us free choice of where to position particular node within container. 

Apart from the vpos and hpos LayoutInfo class consists of the following properties, which will allow further manipulation of the node:

minWidth – sets minimal allowed width of the node
minHeight – sets minimal allowed height of the node
maxWidth – sets maximal allowed width of the node
maxHeight – sets maximal allowed height of the node
height – sets height of the node
width – sets width of the node

There are more variables, but I’ll leave them for you to exploreJ

That would be all from me today. Hope you enjoyed the read.

Cheers

Wednesday 8 September 2010

How to centre nodes using Stack??

Hi guys,
Hope that your experience with Java FX is growing... Today I’m going to describe another way of centering  nodes in a container or Scene. This time I’ll describe the use of Stack using simple example. Stack class allows us to stack nodes on top of each other. It would be good if at this point you consult JavaFX API in order to better understand the example below. Here is the link:


Let’s begin with example. The outcome of the program looks as follows:


As you can or not see it consists of two elements. First one is Java FX text and second is the address of this very blog, positioned on top of the first element. It suggests that the Stack positions the nodes in back-to-front manner.

Now let’s look what happens when we resize the window:



The elements are still positioned in the centre and on top of each other. Have a look at the source code:
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Stack;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.paint.Color;
import javafx.scene.effect.DropShadow;

Stage {
    title: "Centering nodes - Stack"
    var scene: Scene;

    scene: scene = Scene {
        width: 500
        height: 200
        content: Stack {
           width: bind scene.width
           height: bind scene.height
           content: [
              Text {
                  font: Font.font(null, FontWeight.BOLD, 96)
                  fill: Color.LIGHTGREY
                  content: "JAVA FX"
              } // end Text

              Text {
                  font: Font.font(null, FontWeight.BOLD, 25)
                  fill: Color.LIGHTBLUE
                  effect: DropShadow {
                      color: Color.BLUE
                      radius: 5
                  } // end DropShadow
                  content: "www.javafxscripting.blogspot.com"
              } // end Text
           ] // end Stact content
        } // end Stack
    } // end Scene
} // end Stage


As you can see from the source code the object literal for Stack class is as follows:

Stack {
           width: bind scene.width
           height: bind scene.height
           content: [
                ....CODE OMMITED.....
                ]
}

There is nothing unusual about the code, so how the magic happens?? It is simple, Stack has two variables called nodeVPos and nodeHPos which are set to CENTER by default. Lets modify the code above and include the following:

Stack {
           width: bind scene.width
           height: bind scene.height
           nodeVPos: VPos.BOTTOM
           nodeHPos: HPos.RIGHT
           content: [
                ....CODE OMMITED.....
                ]
}

The outcome would be:



In order for the code to work the following libraries must be included:
import javafx.geometry.HPos;
import javafx.geometry.VPos;

I will not describe those at the moment, but you are free to explore them yourselfJ

The order in which the nodes are going to appear is dependent on how they are coded. The first one in the content variable of Stack will be displayed on the bottom. The rest will be displayed on top of the ones that are before them in content. Hope it made some sense;)
The width and height of the Stack is also bound to the scene. It is done so, because we want the Stack to resize with the window and keep the items in the correct position. You can set the variables to other values in order to position the stack whenever you want in the program

I used some effect with the second Text node in order to display the shadow. The class I used is DropShadow. It is one of many effects provided by JavaFX. I will not describe it in this post as I thing it is easy to understand. However, I would really advise you to explore the effect package of JavaFX. If you decide to do so, check the link below to JavaFX API:


I hope you will make use of the information above. If not, you can always ask?
Cheers

Thursday 2 September 2010

How to centre nodes using bind ??

Hi guys,
Haven't been here for a while... Fortunately I came back and I will drop some knowledge today.
I would like to describe one of the techniques used to centre nodes within the scene. In the following application I will use only bind statements, which enables me to keep the text centred even when the window has been resized.

Here you have the window before resizing:


... and here after the window has been resized:




As you can see the text is still in the centre position. It is achieved through using the bind statement. Below I'll reveal the "magic" in the source code:


import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.TextOrigin;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;

Stage {
    title: "Centering Nodes"
    var scene: Scene;
    scene: scene = Scene {
        width: 400
        height: 100
        var textNode: Text;
        content: textNode = Text {
                layoutX: bind (scene.width - textNode.layoutBounds.width) / 2
                layoutY: bind (scene.height - textNode.layoutBounds.height) / 2
                textOrigin: TextOrigin.TOP
                font : Font.font(null, FontWeight.BOLD, 16)
                content: "www.javafxscripting.blogspot.com"
            } // end Text
    } // end Scene
} // end Stage


Most of the code should be clear for you guys as it was described in previous posts. If you cannot understand scroll below and read the posts. I will concentrate on the following piece of code, which keeps the text centred:


Text {
                layoutX: bind (scene.width - textNode.layoutBounds.width) / 2
                layoutY: bind (scene.height - textNode.layoutBounds.height) / 2
                textOrigin: TextOrigin.TOP
                font : Font.font(null, FontWeight.BOLD, 16)
                content: "www.javafxscripting.blogspot.com"
} // end Text


layoutX and layoutY is responsible for positioning the node at the proper coordinates. In this case  they are both calculated. As you can remember bind "glues" two variables together. In the listing both layoutX and layoutY is dependent on the product of:

 (scene.width - textNode.layoutBounds.width) / 2

and

(scene.height - textNode.layoutBounds.height) / 2.

Those are in turn dependent on the width and height of the scene. Therefore, every time the we resize the window the values change and the position of the text is calculated again and text moved to the appropriate position. Simple...

I know what you wan to ask now. What the hell is textNode.layoutBounds.height and textNode.layoutBounds.width??  
The answer is very simple as well. textNode is a reference to the text node(see listing above). layoutBounds is responsible for holding information about the borders of the particular node. This example uses the width and height in order to calculate the position in which drawing should begin.

That's all for now. Hope you all can work something out from the example above. If not.... why not ask a question?