This lesson explains the node architecture and scene graph that underly the JavaFX Script Programming Language, and includes information on the Scene, Node, and Group classes. In this lesson you will build a graphical scene, create a group of nodes, and apply a transformation to the group. Refer to Using Declarative Syntax for more information on the concept of declarative syntax.
|
Contents
The JavaFX Script Programming language is based on a scene graph. The scene graph is a tree-like data structure which defines a hierarchy of graphical objects in a scene. A single element in the scene graph is called a node. Each node has one parent except for the root node, which has no parent. Each node is either a leaf node or a branch. A leaf node has no children. A branch node has one or more children.
JavaFX nodes handle different types of content such as UI components, shapes, text, images, and media. Nodes can be transformed and animated. You can also apply various effects to nodes.
In this lesson, you will create an application with three nodes: a circle, text, and an image, as shown below.
Figure 1: The Nodes example
The application is created using the common profile API and can be run both on mobile devices and desktop platforms. If you want to learn more about the desktop platform API, refer to the JavaFX API. The screen captures provided in this lesson are taken from a desktop application.
JavaFX renders everything on a scene. You can think of the scene as a drawing surface for graphical content. The scene is a container that holds the scene graph nodes.
In any JavaFX GUI application, you create a scene and add nodes to it. You can modify the graphical scene by applying effects, transformations, and animation. The JavaFX runtime takes care of any changes in the graphical scene and performs any necessary repaints for you.
The javafx.scene.Node class is the base class for the scene graph nodes. All other node classes, for example javafx.scene.shape.Circle, inherit from the Node class. For a complete list of instance variable and functions, see the API documentation for the Node class.
The Node class defines a local coordinate system in which the X coordinate increases to the right, and the Y coordinate increases downwards.
Nodes can be changed by applying transformations such as translation, rotation, scaling, and shearing. For example, a translation moves the origin of the node's coordinate system along either the X or Y axis, or both. To define the translation, set the values for the translateX or translateY variables or both.
JavaFX provides powerful support for effects available through the javafx.scene.effect and javafx.scene.effect.light packages. You can see some of the applied effects as well as transformations in Quick JavaFX GUI Overview. Note that the packages are available only in the desktop profile API.
Nodes can receive mouse and keyboard events. You can define functions to be notified when such events occur. For details, see Bringing Interactivity to GUI Elements.
Nodes can be grouped together and treated as a single entity. If you need to provide common behavior for several nodes, group them, and define the required behavior for the whole group. The javafx.scene.Group class represents a group of nodes.
Now you will create a simple application as shown in Figure 1. The graphical scene of this application contains three nodes displayed below on separate windows. They are a shape object (a circle), text, and an image.
Figure 2: Three nodes on separate windows: a circle, text, and an image
First you will add the nodes to the scene as separate nodes. Then you will group them and apply a transformation to the whole group.
Create an application window with the title "Nodes". For details, see Using Declarative Syntax. The following code creates the window.
Note: For the mobile version of the application, this step is required to define the scene.
import javafx.stage.Stage;
Stage {
title: "Nodes"
}
|
A scene is declared using the Scene object literal. You will set the scene's width to 220 pixels, its height to 170 pixels, and give it a light blue background.
- Add import statements for the
javafx.scene.Scene and javafx.scene.paint.Color classes.
- Declare the
Scene object literal.
- Define the
fill variable to set the background for the scene.
- Define the
width, and height attributes of the Scene object. This step is required only for the desktop version of the demo to specify the dimension of the application window. For details, see the Using Declarative Syntax lesson.
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
Stage {
title: "Nodes"
scene: Scene {
fill: Color.LIGHTBLUE
width: 220
height: 170
}
}
|
This code produces the following output.
Figure 3: A scene with light blue background
You add a node to the scene by declaring this node as an element of the content of the scene. The content variable of the scene, which is a sequence of nodes, defines the graphical content of your application.
The first node is a circle. For details on the Circle class, see Using Declarative Syntax. You will paint the boundary of the circle with yellow color.
- Import the
javafx.scene.shape.Circle class.
- Define the
content variable of the scene.
- Add the
Circle object literal to the content variable.
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
Stage {
title: "Nodes"
scene: Scene {
fill: Color.LIGHTBLUE
width: 220
height: 170
content: Circle {
centerX: 50 centerY: 50 radius: 50
stroke: Color.YELLOW
fill: Color.WHITE
}
}
}
|
The modified code gives you the following output.
Figure 4: A scene with a circle node
- Add an import statement for the
javafx.scene.text.Text class.
- Add the
Text object literal to the content variable.
By default the text node will be placed at the point (0,0), which means that the left bottom point of the first character will be placed at (0,0). For this reason, the text is not visible in the application window when the code is compiled and run. In the next step, the default location will be changed so that text is visible.
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
Stage {
title: "Nodes"
scene: Scene {
width: 220
height: 170
fill: Color.LIGHTBLUE
content: [
Circle {
centerX: 50 centerY: 50 radius: 50
stroke: Color.YELLOW
fill: Color.WHITE
},
Text {
content: "Duke"
}
]//Content
}//Scene
}//Stage
|
Use square brackets to specify a sequence of nodes and commas to separate its elements.
You can change the default location by applying a rotation transformation. The rotation is specified by an anchor point and an angle. The node will be rotated clockwise around the anchor point by the specified angle.
To calculate the necessary values, look at Figure 5. If you take the point (10, 100) as an anchor point and draw a circle with a radius equal to the distance to the left bottom point of the text node, then part of this circle falls inside the circle node. Moving the text node along this circle by 33 degrees clockwise gives the result shown in Figure 5.
- Add an import statement for the
javafx.scene.transform.Transform class.
- Define the
transforms variable of the text node to rotate the node by 33 degrees around the point (10,100).
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import javafx.scene.transform.Transform;
Stage {
title: "Nodes"
scene: Scene {
width: 220
height: 170
fill: Color.LIGHTBLUE
content: [
Circle {
centerX: 50 centerY: 50 radius: 50
stroke: Color.YELLOW
fill: Color.WHITE
},
Text {
transforms: Transform.rotate(33, 10, 100)
content: "Duke"
}
]//Content
}//Scene
}//Stage
|
The modified code provides the following output.
Figure 5: A scene with a circle and text nodes
JavaFX applications can display images that are stored either on the Internet or in the local directory of your computer. The images are displayed using the ImageView and Image classes, and the url variable which points to the location of the image. In case you use an image from the Internet, its url variable which indicates the URL, is specified as a URI. In case you refer to an image from the local directory, its url variable which indicates the path to the directory, is specified using the __DIR__ variable.
If you keep an image on the Internet, you need an Internet connection in
order to display it in the application.
The example from this section uses an image of Duke from the Java Tutorials stored in the local directory. The example specifies the image
using the __DIR__ variable. By default, it points to the current
directory, so make sure that the image is located in the same directory
as the application's compiled classes. To run the application on the
mobile emulator, make sure that the image is packed into the application
jar file along with the compiled classes.
By default, the left upper point of the image node is placed in the
point (0,0). The dimensions of this image fit exactly into the area over
the circle node.
For more information about the ImageView and Image classes, see the
JavaFX API. For more details on the use of images, see Creating Animated Objects.
- Add import statements for the
Image and ImageView classes from the javafx.scene.image package.
- Add the
ImageView object literal to the content variable.
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import javafx.scene.transform.Transform;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
Stage {
title: "Nodes"
scene: Scene {
width: 220
height: 170
fill: Color.LIGHTBLUE
content: [
Circle {
centerX: 50 centerY: 50 radius: 50
stroke: Color.YELLOW
fill: Color.WHITE
},
Text {
transforms: Transform.rotate(33, 10, 100)
content: "Duke"
},
ImageView {
image: Image {url: "{__DIR__}dukewave.png"}
}
]//Content
}//Scene
}//Stage
|
You created an application whose graphical scene contains three nodes. The output is shown in the following image.
Figure 6: A scene with three nodes
Now add the nodes to a group and then add the group to the content variable of the scene.
- Add an import statement for the
javafx.scene.Group class.
- Modify the declaration of the
content variable for the scene so that it contains the Group object literal.
- Move all nodes to the
content variable of the Group. The code appears as follows.
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import javafx.scene.transform.Transform;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.Group;
Stage {
title: "Nodes"
scene: Scene {
width: 220
height: 170
fill: Color.LIGHTBLUE
content: Group {
content: [
Circle {
centerX: 50 centerY: 50 radius: 50
stroke: Color.YELLOW
fill: Color.WHITE
},
Text {
transforms: Transform.rotate(33, 10, 100)
content: "Duke"
},
ImageView {
image: Image {url: "{__DIR__}dukewave.png"}
}//ImageView
]//Content
}//Group
}//Scene
}//Stage
|
Note the importance of the order in which you add objects to your group. This order defines how those objects are laid out. If you add the circle node last (after the text and image nodes), then the circle will be drawn over the two other objects. Because the circle has a fill color, these nodes will not be seen.
Finally, define the translation for the group of nodes to move the group to the center of the window as shown in the following code.
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.text.Text;
import javafx.scene.transform.Transform;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.Group;
Stage {
title: "Nodes"
scene: Scene {
width: 220
height: 170
fill: Color.LIGHTBLUE
content: Group {
translateX: 55
translateY: 10
content: [
Circle {
centerX: 50 centerY: 50 radius: 50
stroke: Color.YELLOW
fill: Color.WHITE
},
Text {
transforms: Transform.rotate(33, 10, 100)
content: "Duke"
},
ImageView {
image: Image {url: "{__DIR__}dukewave.png"}
}//ImageView
]//Content
}//Group
}//Scene
}//Stage
|
This modification shifts all three nodes simultaneously as displayed in the following image.
Figure 7: A group of nodes shifted to the center of the window
For your reference, here is the complete code of this example application.
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.text.Text;
import javafx.scene.transform.Transform;
Stage {
title: "Nodes"
scene: Scene {
width: 220
height: 170
fill: Color.LIGHTBLUE
content: Group {
translateX: 55
translateY: 10
content: [
Circle {
centerX: 50 centerY: 50 radius: 50
stroke: Color.YELLOW
fill: Color.WHITE
},
Text {
transforms: Transform.rotate(33, 10, 100)
content: "Duke"
},
ImageView {
image: Image {url: "{__DIR__}dukewave.png"}
}//ImageView
]//Content
}//Group
}//Scene
}//Stage
|
In this lesson you learned how to build a graphical scene, add nodes to the scene, group nodes, and apply a transformation to the group. Now you can proceed with creating more sophisticated graphical applications.
Do you have comments about this article? We welcome your participation in our community. Please keep your comments civil and on point. You may optionally provide your email address to be notified of replies - your information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.
|