Developing Your Second JavaFX Program: "More Cowbell!" (Getting a Jump Start in JavaFX) Part 2

Creating an Instance of the Model, and the Magic of Binding

One of the powerful aspects of JavaFX is binding, which enables the application’s UI to easily stay in sync with the state, or model, of the application. The model for a JavaFX application is typically held in one or more classes, in this case the AudioConfigModel class. Look at the following snippet, taken from Listing 1-3, in which we create an instance of this model class.

AudioConfigModel acModel = new AudioConfigModel();

There are several graphical node instances in the scene of this UI (recall that a scene consists of a sequence of nodes). Skipping past several of them, we come to the graphical nodes shown in the following snippet that have a property bound to the selectedDBs property in the model.

tmpA-26_thumb[2]

 

 

 

tmpA-27_thumb[2]


As shown in this snippet, the text property of the Text object is bound to an expression. The bind function contains an expression (that includes the selectedDBs property), which is evaluated and becomes the value of the text property. Look at Figure 1-7 (or check the running application) to see the content value of the Text node displayed to the left of the slider.

Notice also in the snippet that the value property of the Slider node is bound to the selectedDBs property in the model as well, but that it uses the bindBidirectional() method. This causes the bind to be bidirectional, so in this case when the slider is moved, the selectedDBs property in the model changes. Conversely, when the selectedDBs property changes (as a result of changing the genre), the slider moves.

Go ahead and move the slider to demonstrate the effects of the bind expressions in the snippet. The number of decibels displayed at the left of the slider should change as the slider is adjusted.

There are other bound properties in Listing 1-3 that we point out when we walk through the model class. Before leaving the UI, we point out some color-related concepts in this example.

Colors and Gradients

The following snippet from Listing 1-3 contains an example of defining a color gradient pattern, as well as defining colors.

tmpA-28_thumb[2]

If the JavaFX API docs are handy, first take a look at the javafx.scene.shape.Rectangle class and notice that it inherits a property named fill that is of type javafx.scene.paint.Paint. Looking at the JavaFX API docs for the Paint class, you’ll see that the Color, LinearGradient, and RadialGradient classes are subclasses of Paint. This means that the fill of any shape can be assigned a color or a gradient.

To create a LinearGradient, as shown in the snippet, you need to define at least two stops, which define the location and color at that location. In this example the offset value of the first stop is 0.0, and the offset value of the second stop is 1.0. These are the values at both extremes of the unit square, the result being that the gradient will span the entire node (in this case a Rectangle). The direction of the LinearGradient is controlled by its startX, startY, endX, and endY values. In this case, the direction is only vertical because the startY value is 0.0 and the endY value is 1.0, whereas the startX and endX values are both 0.0.

Note that in the Hello Earthrise example in Listing 1-1, the constant named Color.WHITE was used to represent the color white. In the previous snippet, the web function of the Color class is used to define a color from a hexadecimal value.

The Model Class for the Audio Configuration Example

Take a look at the source code for the AudioConfigModel class in Listing 1-4.

Listing 1-4. The Source Code for AudioConfigModel.java package projavafx.audioconfig.model;

The Source Code for AudioConfigModel.java package projavafx.audioconfig.model;

 

 

 

 

 

The Source Code for AudioConfigModel.java package projavafx.audioconfig.model;

Defining Change Listeners in the Model class

Change listeners are a construct that helps enable declarative programming. For example, the change listener shown in this snippet executes whenever the selected index property of the selection model associated with the ChoiceBox changes:

tmpA-31_thumb[2]

 

 

tmpA-32_thumb[2]

What causes selectedIndexProperty of the genreSelectionModel to change, though? To see the answer to this, we have to revisit some code in Listing 1-3. In the following code snippet, the items method of the ChoiceBoxBuilder is used to populate the ChoiceBox with items that each contain a genre.

tmpA-33_thumb[2]

This snippet from the model code in Listing 1-4 contains the collection to which the ComboBox items are bound:

tmpA-34_thumb[2]

When the user chooses a different item in the ChoiceBox, the change listener is invoked. Looking again at the code in the change listener, you’ll see that the value of the selectedDBs property changes, which as you may recall, is bidirectionally bound to the slider. This is why the slider moves when you select a genre in the combo box. Go ahead and test this out by running the Audio Config program.

■ Note Associating the items property of the ChoiceBox with an ObservableList causes the items in the ChoiceBox to be automatically updated when the elements in the underlying collection are modified.

Next post:

Previous post: