Building GUI Applications With JavaFX

Lesson 4: Creating Graphical Objects


You have already learned enough about the JavaFX Script programming language to start creating more sophisticated graphical objects. This section describes the typical process of creating graphics by using the JavaFX Script programming language. In this lesson, you will create a design for an audio player that includes a play button as shown in the following figure.

Figure 1: Play Button

To create the button, you choose from a variety of JavaFX objects and features described in the Quick JavaFX GUI Overview lesson. Those objects and features are a rectangle, a circle, a polygon, and a gradient effect. Then you combine those features to achieve the desired graphics for the button.


Note: This lesson uses a limited number of graphical features from the JavaFX Script programming language. You can combine other effects and features to create UI elements such as slider bars, progress bars, buttons, and search fields. Alternatively, you can use a set of predefined components from the javafx.scene.control package.

Create a file with an .fx extension. Avoid using file names that match the names of existing classes, instance variables, or reserved words because this leads to errors during compilation. For more information about existing classes, variables, and reserved words, see JavaFX Script API and Learning the JavaFX Script Programming Language.

To display the graphics, first create a window.


Note: For the mobile version of the application, this step is required to define the scene.

To create a window:

  1. Add an import statement for the javafx.stage.Stage class.

  2. Declare the Stage object literal.

  3. Define the title attribute of the Stage object. For details, see the Using Declarative Syntax lesson.

Here is the code:

import javafx.stage.Stage;                        //required to
//render a window

Stage {
title: "Play Button"
}

Within the Stage, set the scene to hold Node objects such as a circle or a rectangle.

To define the scene and fill it with white:

  1. Add import statements for the javafx.scene.Scene and for the javafx.scene.paint.Color classes.

  2. Declare the Scene object literal.

  3. Define the fill variable of the Scene object.
    The fill variable is used to fill the background with either a color or a gradient.

  4. Specify content variable within the Scene.
    The content variable is used to hold objects of the Scene.

  5. Define the width and height attributes of the Scene object.
    This step is required only for the desktop version of the example to specify the dimension of the application window. For details, see the Using Declarative Syntax lesson.

The following code sets the scene and fills it with white:

import javafx.scene.Scene;                   //required to
//display objects of Node
//type such as a circle
//and rectangle
javafx.scene.paint.Color //required to draw a gradient


Stage {
...
scene: Scene {
width: 250
height: 350
fill: Color.WHITE
content: [
//objects that appear on the scene
]//Content
}//Scene
}//Stage

For more information about nodes and the Scene class, see the Presenting UI Objects in a Graphical Scene lesson and JavaFX Script API.

Now you can proceed to specify the objects within the scene. The button consists of a rectangle and a circle. Specify the rectangle and the circle within a group.

To specify objects:

  1. Add an import statement for the javafx.scene.Group class.

  2. Declare the Group object literal.

  3. Specify the content variable within the Group.
    The content variable is used to hold objects of the Group.

The code looks like the following:

import javafx.scene.Group;            //required to group
//objects to be able
//to operate with them as a unit

Stage {
...
scene: Scene {
...
content: [
Group {
content: []
}//Group
]//Content
}//Scene
}//Stage

For more information about the Group class, see JavaFX Script API.

To create a button substrate, use four Rectangle objects, as shown in the following figure.

Figure 2: Button Substrate

The Rectangle objects form the following parts of the button substrate:

  • Rectangle 1 - Top part of the lower gradient area
  • Rectangle 2 - Bottom part of the lower gradient area
  • Rectangle 3 - Upper gradient area
  • Rectangle 4 - Stroked outline

Perform the following steps to create the top part of the lower gradient area:

  1. Add the javafx.scene.shape.Rectangle, javafx.scene.paint.LinearGradient, and javafx.scene.paint.Stop imports.

  2. Declare the Rectangle object literal and its variables.
    For more information about the Rectangle class, see the Using Declarative Syntax lesson and the JavaFX Script API.

    Here is the code that accomplishes these two steps:

    import javafx.scene.shape.Rectangle;      //required to render a rectangle
    Rectangle {
    x: 48, y: 168, width: 150, height: 25
    }//Rectangle

  3. Fill the rectangle with a gradient fill from deep sky blue to light sky blue by using the fill variable.

This type of even shading between two colors is called a linear gradient. The effect is produced by using the javafx.scene.paint.LinearGradient class.

Here is the code to produce that effect:

import javafx.scene.paint.LinearGradient; //required to create
import javafx.scene.paint.Stop; //a linear gradient

Rectangle {
...
fill: LinearGradient {
startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
proportional: true
stops: [
Stop {offset: 0.0 color: Color.web("#99ddff")},
Stop {offset: 1.0 color: Color.web("#337799")}
] //stops
}//fill
}//Rectangle

  • startX, startY, endX, and endY instance variables control the horizontal and vertical direction and the size of the gradient. Each pair - startX, startY and endX, endY - defines the coordinates of the starting and ending points of the gradient. If an ending value of a pair is smaller than the starting value of the same pair, then the direction of the gradient is reversed.


    Note: The values of this variable depend on the proportional variable described in the following paragraph.
  • The proportional variable defines whether the values of startX, startY, endX, and endY are scaled. If the proportional variable is set to true, the starting and ending points of the gradient should be specified relative to the window square (0.0 — 1.0), and will be stretched across the window. If the proportional variable is set to false, the starting and ending points should be specified as absolute pixel values and the gradient will not be stretched at all.

    For example, if the startY is set to 30, endY set to 100, both startX and startY are set to 0, and the proportional variable is set to false, the Y starting point of the gradient will be a point 30 pixels below the title bar of the window and the Y ending point of the gradient will be a point 100 pixels below. If the startY is set to 0.5, endY is set to 1.0, the proportional variable is set to true, and startX and endX are both set to 0, the following apply:

    • The Y starting point of the gradient will be a point that has a Y value that is 50% of the height of a shape.
    • The Y ending point will be a point that has a value that is 100% of the height of a shape.

  • The stops is a sequence of Stop variables that defines how to distribute colors along the gradient. The offset variable of Stop defines the point where the gradient should be a particular color. The offset is specified relative to the scene square and its values should range from 0.0 to 1.0. The Color variable defines the color of the gradient. As a value of Color, you can specify either an explicit color, for example, Color.LIGHTSKYBLUE, or a hexadecimal web code for this color, for example, Color.web("FFFFFF"). For more information about the linear gradient, see JavaFX Script API.

As a result, this code creates a rectangle with the upper left corner at 48, 168. The rectangle is placed in the center of the window and has the size of 150 by 25 pixels, and is filled with a linear gradient that spreads vertically.

Figure 3: A Rectangle Filled With Gradient

Construct three more rectangles as shown in the Substrate.fx file.

Now you can add the play indicator to the button.

To add the indicator to the button:

  1. Add the javafx.scene.shape.Circle import.

  2. Declare the circle and its variables by using the Circle class.
    For more information about the Circle class, see the Using Declarative Syntax lesson and the JavaFX Script API.

    import javafx.scene.shape.Circle;        //required to render a circle
    Circle {
    centerX: 122 centerY: 122 radius: 38
    fill: LinearGradient {startX: 0.0, startY: 1.0, endX: 0.0, endY: 0.0,
    proportional: true
    stops: [
    Stop {offset: 0.0 color: Color.web("#66aacc")},
    Stop {offset: 1.0 color: Color.web("#99ddff")}
    ] //stops
    } //fill
    stroke: Color.web("#66aacc")
    strokeWidth: 2.0
    }

    This code creates the following circle.

    Figure 4: Circle Element of the Play Indicator

  3. Add the javafx.scene.shape.Polygon import.

  4. Add two triangles constructed by using the Polygon class.
    The upper triangle displays a commonly used play symbol, while the lower triangle creates a shadow effect for it. Note that this is the most primitive way of rendering shadow effect. You will learn how to create the shadow effect by using the javafx.scene.effect package in the Desktop section of this lesson.
import javafx.scene.shape.Polygon;  //required to render a triangle

// Polygon1: lower triangle
Polygon {
points: [142.0, 126.0, 113.0, 108.0, 111.0, 143.0]
fill: Color.web("#337799")
},//Polygon1

//Polygon2: upper triangle
Polygon {
points: [142.0, 123.0, 110.0, 105.0, 110.0, 140.0]
fill: Color.web("#ffffff")
}//Polygon2


When added to the application, this code creates two triangles. The following screen capture shows the play indicator.

Figure 5: Play Indicator

Now you are ready to run the entire example. The following code is available in the PlayButtonCommon.fx file. When compiled and run, this application produces the following window.

Figure 6: Completed Play Button

Desktop Profile

To visually enhance the application and to use the power of the desktop profile, you can add a reflection effect to the button and implement a shadow effect for the triangle by using the DropShadow effect.


Note: The application from this section is based on the example you created in the "Common Profile" section.

In this step, you create a drop shadow for the play triangle instead of using an additional contrast triangle.

To create a drop shadow:

  1. Add import statements for the javafx.scene.effect.DropShadow class.

  2. Remove the code fragment for the Polygon1.

  3. Re-define the construct for the Polygon2

The following code applies a drop shadow effect to the Polygon object by specifying the color of the shadow and the number of pixels the shadow is displaced from Polygon.

import javafx.scene.effect.DropShadow;         //required to apply
//the shadow effect

//Polygon2: upper triangle
Polygon {
points: [142.0, 123.0, 110.0, 105.0, 110.0, 140.0]
fill: Color.web("#ffffff")
effect: DropShadow {
color: Color.web("#337799")
offsetY: 5
offsetX: 2
}
}//Polygon2

The previous code produces the effect shown in the following screen capture. Notice that the shadow is somewhat smooth and comparatively natural, rather than having a constructed, triangle shape.

Figure 7: Play Button With a Drop Shadow

In this step, you add a reflection of the play button.
To apply the reflection effect:

  1. Add the javafx.scene.effect.Reflection import statement.

  2. Specify the effect using the effect and Reflection variables.

Although the reflection produces a substantial visual enhancement to the button, it requires only the following line of code:

import javafx.scene.effect.Reflection;            //required to
//apply a reflection effect


content: [
Group {
content: [
...
]
effect: Reflection {fraction: 0.5 topOpacity: 0.5 topOffset: 0.5}
}//Group
]//Stage

The reflection object literal has a fraction instance variable that defines the percentage of the button area that is visible in the reflection. The topOpacity variable defines the opacity of the reflection, and topOffset defines the distance between the bottom of the button and the top of the reflection.


Note: The fraction and the topOpacity variables can take only values ranging from 0.0 to 1.0.

After you apply the effects, the application will look like the following:

Record button with reflection
Figure 8: Play Button With Reflection

For more information about the reflection effect, see JavaFX Script API. For a complete list of graphical effects in JavaFX API, see The Quick JavaFX GUI Overview lesson. You can find the complete source code for the application in the PlayButtonDesktop.fx file.

0 comments:

Post a Comment