Controls
The first releases of JavaFX focused mainly on the foundations of the JavaFX platform, the JavaFX script language, and the runtime, at the expense of ready-made UI components. A set of Swing classes were built around the Java Swing components, but they only run on the desktop profile and are not supported on the mobile and TV platforms. Obviously, a portable set of ready-made components was needed—one that could be used across the various JavaFX platforms. The early introduction of the JavaFX control package brought a taste of things to come, with its ready-made support for separation of controls that handle interaction with the user, and skins that define the visual representation of the control. However, only one built-in control, TextBox, was released at that time. With JavaFX 1.2, 11 new controls have been added to the TextBox provided in JavaFX 1.1: Button, CheckBox, RadioButton, ToggleButton, Label, Hyperlink, ScrollBar, Slider, ProgressBar, ProgressIndicator, and ListView. Figure 13 illustrates how all of these controls are displayed.
The first two controls shown in Figure 13 are Button controls. Both instances use the same class, except that the first button has its text variable set to "My Button", whereas the second button instance is using a graphic. For example, here's the object literal for the first button instance:
Button { text: "My Button" action: function() { Alert.inform("My Button pushed"); } }
For the second button, the image is displayed using a graphic instance variable that contains an ImageView. graphic is not constrained to being an Image, but rather can be any kind of JavaFX node. Here's an example object literal for the second button:
Button { graphic: ImageView { image: Image { url: "{__DIR__}images/media-playback-start.png" } } } action: function() { Alert.inform("Play Button pushed"); } }
You can even include both a text and a graphic, and you can indicate the order in which these controls should appear, placing the graphic either to the left or right of the text. In both cases, the action variable contains a function that's invoked when the button is clicked. These two examples use the Alert dialog (discussed later in this article.)
The RadioButton and ToggleButton controls have an optional toggleGroup variable. If you want a set of RadioButtons or ToggleButtons to be exclusive of each other (selecting one button in the group automatically deselects the others), assign the same ToggleGroup instance to each of the buttons. For example:
var toggleGroup1 = ToggleGroup{}; RadioButton { text: "Option 1!" toggleGroup: toggleGroup1 } RadioButton { text: "Option 2!" toggleGroup: toggleGroup1 } RadioButton { text: "Option 3!" toggleGroup: toggleGroup1 }
CheckBox, ToggleButton, and RadioButton do not have action variables. To cause an action when one of these controls is selected or deselected, it's necessary to add an on replace trigger to the selected instance variable. This can be done by using the override keyword in the object literal when the control is created. For example:
CheckBox { text: "Check me!" allowTriState: false override var selected on replace { if(selected) Alert.inform("Check Me is selected!"); } }
All the controls implement a new JavaFX theme called Caspian. However, you can set your own fonts and colors by using Cascading Stylesheets (CSS). JavaFX stylesheets are similar to their HTML cousins, but have a few minor differences. I would need a separate article to explain it all, but I'll illustrate a simple example by setting the font for a Hyperlink object.
In the Caspian theme, the default font and point size are Veranda 11-point. In this example, we want to change that setting to a bold italic sans-serif 35-point. First, we must create a CSS stylesheet whose file would contain an entry like the following:
"Hyperlink" { text-font: bold italic 35pt "sans-serif"; }
This particular entry will set the textFont variable on all javafx.scene.control.Hyperlink objects. Other options support CSS ID selectors to apply the style to an individual node, class selectors to apply the styles to classes of nodes, and certain pseudo-classes that allow you to set styles on certain conditions such as hover and focused. To use this stylesheet, you must point your Scene to the CSS stylesheet file through the stylesheets sequence variable. Because stylesheets is a sequence, there may be more than one stylesheet. For our hyperlink example, we assign the stylesheet to the stylesheets instance variable by using the object literal syntax. (" DIR " is a built-in variable indicating the directory where the current script is located.)
Stage { title: "Hyperlink CSS StyleSheet Example" width: 500 height: 100 scene: Scene { stylesheets: ["{__DIR__}HyperlinkStyleSheet.css"] content: [ Hyperlink { text: "http://www.javafx.com" action: function() { Alert.inform("http://www.javafx.com"); } } ] } }
This example will produce the display shown in Figure 14, with the sans-serif 35-point font.
I've only touched the surface of these new controls—there's a lot more to them. While these controls should satisfy most needs, it's also possible to create your own controls and skins by extending javafx.scene.control.Control and javafx.scene.control.Skin. In the open source JFXtras project I mentioned earlier, many of the components are custom controls.