Sun Java Solaris Communities My SDN Account

Article

JavaFX 1.2 UI Control Components: Part Two: Nodes and Buttons

 
By Robert Eckstein, April 2010  

JavaFX SDK 1.2 introduces a new set of user-interface (UI) control components for JavaFX programmers. Previously, JavaFX UI Components simply "borrowed" their functionality from the underlying Swing components, which prevented their use in anything other than the desktop profile. The JavaFX SDK 1.2 components, however, take advantage of the more powerful JavaFX scene graph, which not only increases portability, but also allows JavaFX programmers to create more compelling graphical capabilities. In Part One in this series we looked at new layout classes in Java FX. Previous articles have examined RSS and storage, and JavaFX charts. Here, we take a closer look at the Button classes.

Nodes and the Scene Graph

JavaFX UI components all inherit from the Node class, which contains a wealth of properties common to all graphical components that can work with JavaFX's scene graph.

What is a scene graph? According to the official documentation, a scene graph is a set of tree data structures in which each node is either a leaf node with no sub-nodes or a branch node with possible sub-nodes. In addition, each node may or may not have a parent node.

Here are some other rules and characteristics taken directly from the JavaFX documentation:

  • Branch nodes are either of type Group or of type CustomNode, or subclasses thereof.
  • Leaf nodes include such classes as javafx.scene.shape.Rectangle, javafx.scene.text.Text, javafx.scene.image.ImageView, javafx.scene.media.MediaView.
  • Only a single node within each scene graph tree will have no parent, which is often referred to as the root node.
  • There may be several trees in the scene graph. Some trees may be part of a Scene, in which case they are eligible to be displayed. Other trees might not be part of any Scene.
  • Each node in the scene graph can be given a unique String identifier. A convenience function called lookup(String) (java.lang.String) can be used to find a node with a unique id within the scene graph, or within a subtree of the scene graph.
  • Note that the Node class uses the traditional computer graphics "local" coordinate system in which the x axis increases to the right and the y axis increases downwards.
  • Any Node can have transformations applied to it. These include translation, rotation, scaling, or shearing transformations. Multiple transformations may be applied to a node by specifying an ordered chain of transforms. The order in which the transforms are applied is defined by the sequence specified in the transforms variable.
  • Since every Node has transformations, every Node's geometric bounding rectangle can be described differently depending on whether or not transformations are accounted for.
  • At their simplest, Nodes have a read-only boundsInLocal variable which specifies the bounding rectangle of the Node in untransformed local coordinates. boundsInLocal includes the Node's shape geometry, including any space required for a non-zero stroke that may fall outside the local position/size variables, its clip and effect variables (if set).
  • The layoutBounds variable defines the rectangular bounds of a Node that should be used as the basis for layout calculations. By default this will be equal to boundsInLocal plus transforms set in the transforms variable but does NOT include transforms set by the explicit translateX, translateY, scaleX, scaleY, and rotate variables.
  • Each Node also has a read-only boundsInParent variable which specifies the bounding rectangle of the Node after all transformations have been applied, including those set in transforms, translateX, translateY, scaleX, scaleY, and rotate. It is called "boundsInParent" because the rectangle will be defined in terms of the parent Node's coordinate system.

The ButtonBase Class

Before we jump into the various styles of buttons that are available in JavaFX, let's introduce their abstract superclass: javafx.scene.control.ButtonBase. ButtonBase attempts to consolidate functionality that is common to all buttons. In this case, ButtonBase contains one boolean property, armed, that indicates whether a mouse release on the button will cause the button's action to be invoked, as shown in Table 1.

Table 1. Variables in the ButtonBase class
Name Type Access Description
armed Boolean public-read Indicates that the button has been "armed" so that a mouse release will cause the button's action to be invoked.

The Button Class

First, let's take a look at the Button class. Table 2 shows the variables that are present in this class.

Table 2. Variables in the Button class
Name Type Access Description
strong Boolean Public Indicates a "stronger colored" button. A strong Button is rendered differently from normal Buttons. action function():Void Public The button's action, which is invoked when the user releases the mouse inside the button.
action function():Void Public The button's action, which is invoked when the user releases the mouse inside the button.

Button also inherits the properties of the ButtonBase and Node class. Note the addition of the strong property. The strong property is a boolean that indicates whether the Button should appear as a "stronger colored" button, perhaps to indicate to the user that it is a default button. Here is an example of how to use the Button class.

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.control.Button;

Stage {
    title: "Application title"
    scene: Scene {
        width: 250
        height: 80
        content: [
            Button {
                text: "OK"
                translateX: 10
                translateY: 10
                strong: true
                font: Font {size: 24 name: "Tahoma"}

                action: function() {
                    println("Button pressed!");
                }
            }

        ]
    }
}

Attached to the action property is an anonymous function that simply prints out a message when the button is pressed. However, you can customize the function to perform whatever action your program deems necessary. Figure 1 shows the resulting button, with and without the strong attribute selected.

Figure 1. A Button, without and with the strong property enabled

The CheckBox Class

Next, let's look at an example of the CheckBox class. You might be surprised to discover that the checkbox component is a "tri-state" component, having one of three states. These are checked, unchecked, and an undefined state which indicates that its state is determined by its parent. Table 3 shows the properties of the CheckBox class.

Table 3. Variables in the CheckBox class
Name Type Access Description
allowTriState Boolean public Determines whether the user toggling the CheckBox should cycle through all three states: checked, unchecked, and undefined.
Defined Boolean public Determines whether the CheckBox is in the defined state.
Selected Boolean public Indicates whether this CheckBox is checked.

CheckBox uses two boolean attributes to determine which of the three states it is currently in: defined and selected. If a CheckBox is "checked," then it is also by definition defined. A CheckBox is in this state if selected is true and defined is also true. A CheckBox is "unchecked" if selected is false and defined is true. A CheckBox is "undefined" if defined is false, regardless of the state of selected. The following example demonstrates the use of a CheckBox class.

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.CheckBox;


Stage {
    title: "Application title"
    scene: Scene {
        width: 250
        height: 80
        content: [

            CheckBox {
                    text: "Check me!"
                    allowTriState: true
                    defined: false
                    selected: true
            }

        ]
    }
}

The resulting CheckBox example is shown in Figure 2. Note that we have shown each of the three states.

Figure 2. A CheckBox, with the dashed, checked, and unchecked state

The RadioButton Class

Next, let's look at the RadioButton class. A RadioButton is a specialized form of ToggleButton, but it typically uses a ToggleGroup to enforce mutual exclusivity between a series of buttons. In other words, only one radio button can be selected at any given time within a group. Table 4 shows the properties of the RadioButton class.

Table 4. Variables in the RadioButton class
Name Type Access Description
Selected Boolean public Indicates if this ToggleButton is the one that is selected.
toggleGroup ToggleGroup public The group to which this ToggleButton belongs.

Here is a short example of how to define a RadioButton with a ToggleGroup.

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.VBox;

def toggleGroup1:ToggleGroup = ToggleGroup {}

def radioButton1:RadioButton = RadioButton {
    text: "Click me!"
    selected: true
    toggleGroup: toggleGroup1
}

def radioButton2:RadioButton = RadioButton {
    text: "No, Click me!"
    toggleGroup: toggleGroup1
}

def radioButton3:RadioButton = RadioButton {
    text: "Please Click me!"
    toggleGroup: toggleGroup1
}

Stage {
    title: "Application title"
    scene: Scene {
        width: 250
        height: 80
        content: [
            VBox {
                content: [
                     radioButton1, radioButton2, radioButton3

                ]
            }

        ]
    }
}

The result is shown in Figure 3. Note that selecting any of the three buttons will "unselect" the others.

Figure 3. Three RadioButton classes, each sharing a ToggleGroup to enforce mutual exclusivity

The ToggleButton Class

As we mentioned earlier with the RadioButton, the ToggleButton is another form of button, except that the button will remain in the selected state until it is clicked again by the user. Table 5 shows the properties of the ToggleButton class.

Table 4. Variables in the RadioButton class
Name Type Access Description
Selected Boolean public Indicates if this ToggleButton is the one that is selected.
toggleGroup ToggleGroup public The group to which this ToggleButton belongs.

You may have noticed that the properties of RadioButton and ToggleButton are identical. This means that, in addition to RadioButton classes, you can also create ToggleButton classes that belong to a ToggleGroup. If this is done, the behavior is the same: ToggleGroup will enforce a mutual exclusivity with either type of button.

Here is an example of the ToggleButton class in action.

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;

Stage {
    title: "Application title"
    scene: Scene {
        width: 250
        height: 80
        content: [

            ToggleButton {
                    text: "First"
            }

        ]
    }
}

The result is shown in Figure 4, in both its selected and unselected state.

Figure 4. A ToggleButton outside of a ToggleGroup, in both its non-selected and selected state

The Hyperlink Class

Our final button class is one that may surprise Swing programmers: the Hyperlink class. A hyperlink is an HTML-like text label which can respond to rollovers and clicks, similar to a browser. In effect, it is a featureless button (text or image) that has an action function attached to it. Table 5 shows the properties of the Hyperlink class.

Table 5. Variables in the Hyperlink class
Name Type Access Description
visited Boolean public Indicates whether this link should indicate that it has already been "visited".
action function():Void public The button's action, which is invoked when the user releases the mouse inside the button.

Note that there is a visited property, which indicates whether the hyperlink should indicate if it has already been visited. Here is an example of how to use Hyperlink.

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Hyperlink;

Stage {
    title: "Application title"
    scene: Scene {
        width: 250
        height: 80
        content: [

            Hyperlink {
                    text: "http://www.javafx.com"
                    visited: true
                    action: function() {
                        println("Hyperlink pressed!");
                    }
            }

        ]
    }
}

The result is shown in Figure 5. Note that when you press on the text, the action function is called, which will allow you to take the appropriate action, such as re-rendering the display or opening a browser and moving to that page.

Figure 5. A HyperLink node

Summary: More Compelling Graphics

The new set of user-interface (UI) control components for JavaFX programmers found in JavaFX SDK 1.2 enables developers to take advantage of the JavaFX scene graph, which as we have seen, enhances the flexibility and functionality of the Button classes. This, along with the new layout classes, enables JavaFX developers to create more compelling and portable graphical capabilities.

For More Information

Rate This Article

 

Discussion

We welcome your participation in our community. Please keep your comments civil and on point. You can 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.

 
Photo of Robert Eckstein
Robert Eckstein has worked with Java technology since its first release. He was formerly a programmer and editor for O'Reilly Media, Inc., a programmer for Motorola's cellular technology division, and previously worked for Sun Microsystems as a senior staff writer on java.sun.com.

Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.