Animating Nodes in the Scene (Creating a User Interface in JavaFX) Part 4

Using the KeyFrame Action Event Handler

We’re using a different technique in the timeline than demonstrated in the Metronome1 program earlier in the topic (see Figure 2-8 and Listing 2-5). Instead of interpolating two values over a period of time, we’re using the action event handler of the KeyFrame instance in our timeline. Take a look at the following snippet from Listing 2-8 to see this technique in use.

tmpA-97_thumb[2][2][2]

As shown in the snippet, we use only one KeyFrame, and it has a very short time (10 milliseconds). When a KeyFrame has an action event handler, the code in that handler is executed when the time for that KeyFrame is reached. Because the cycleCount of this timeline is indefinite, the action event handler will be executed every 10 milliseconds. The code in this event handler does two things:

• Calls a method named checkForCollision() which is defined in this program, whose purpose is to see whether the ball has collided with either paddle or any of the walls

• Updates the properties in the model to which the position of the ball is bound, taking into account the direction in which the ball is already moving


Using the Node intersectsO Method to Detect Collisions

Take a look inside the checkForCollision() method in the following snippet from Listing 2-8 to see how we check for collisions by detecting when two nodes intersect (share any of the same pixels).

tmpA-98_thumb[2][2][2]

 

 

 

tmpA-99_thumb[2][2][2]

The intersects() method of the Node class shown here takes an argument of type Bounds, located in the javafx.geometry package. It represents the rectangular bounds of a node, for example, the leftPaddle node shown in the preceding code snippet. Notice that to get the position of the left paddle in the Group that contains it, we’re using the boundsInParent property that the leftPaddle (a Rectangle) inherited from the Node class.

The net results of the intersect method invocations in the preceding snippet are as follows.

• If the ball intersects with the bounds of the rightWall or leftWall, the pongAnimation Timeline is stopped and the game is initialized for the next play. Note that the rightWall and left Wall nodes are one-pixel-wide rectangles on the left and right sides of the Scene. Take a peek at Listing 2-8 to see where these are defined.

• If the ball intersects with the bounds of the bottomWall or topWall, the vertical direction of the ball will be changed by negating the program’s Boolean movingDown variable.

• If the ball intersects with the bounds of the leftPaddle or rightPaddle, the horizontal direction of the ball will be changed by negating the program’s Boolean movingRight variable.

■ Tip For more information on boundsInParent and its related properties, layoutBounds and boundslnLocal, see the "Bounding Rectangles" discussion at the beginning of the javafx.scene.Node class in the JavaFX API docs. For example, it is a common practice to find out the width or height of a node by using the expression myNode.getLayoutBounds().getWidth() or myNode.getLayoutBounds().getHeight().

Dragging a Node

As you experienced previously, the paddles of the ZenPong application may be dragged with the mouse. The following snippet from Listing 2-8 shows how this capability is implemented in ZenPong.

tmpA-100_thumb[2][2][2]

 

 

tmpA-101_thumb[2][2][2]

Note that in this ZenPong example, we’re dragging the paddles only vertically, not horizontally Therefore, the code snippet only deals with dragging on the y axis.

Giving Keyboard Input Focus to a Node

In order for a node to receive key events, it has to have keyboard focus. This is accomplished in the ZenPong example by doing these two things, as shown in the snippet below from Listing 2-8:

• Assigning true to the focusTraversable property of the Group node. This allows the node to accept keyboard focus.

• Calling the requestFocus() method of the Group node (referred to by the pongComponents variable). This requests that the node obtain focus.

■ Tip You cannot directly set the value of the focused property of a Stage. Consulting the API docs also reveals that neither can you set the value of the focused property of a Node (e.g., the Group that we’re discussing now). However, as discussed in the second bullet point above, you can call requestFocus() on the node, which if granted (and focusTraversable is true) sets the focused property to true. By the way, Stage doesn’t have a requestFocus() method, but it does have a toFront() method, which should give it keyboard focus.

tmpA-102_thumb[2][2][2]

Now that the node has focus, when the user interacts with the keyboard, the appropriate event handlers will be invoked. In this example, we’re interested in whenever certain keys are pressed, as discussed next.

Using the onKeyPressed Event Handler

When the user presses a key, the handle() method of the anonymous class supplied to the onKeyPressed method is invoked, passing a KeyEvent instance that contains information about the event. This handle method, shown in the preceding snippet from Listing 2-8, compares the getCode() method of the KeyEvent instance to the KeyCode constants that represent the arrow keys to ascertain which key was pressed.

Summary

Congratulations, you have learned a lot in this topic about creating UIs in JavaFX, including the following.

• Creating a user interface in JavaFX, which we loosely based on the metaphor of creating a theater play and typically consists of creating a stage, a scene, nodes, a model, and event handlers, and animating some of the nodes

• The details about using most of the properties and methods of the Stage class, including how to create a Stage that is transparent with no window decorations

• How to use the HBox and VBox layout containers to organize nodes horizontally and vertically, respectively

• The details about using many of the properties and methods of the Scene class

• How to create and apply CSS styles to nodes in your program by associating one or more style sheets with the Scene

• How to handle keyboard and mouse input events

• How to animate nodes in the scene, both with the Timeline class and the transition classes

• How to detect when nodes in the scene have collided

Now that you have learned more about JavaFX user interface development.

Resources

For some additional information on creating JavaFX user interfaces, you can consult the following resources.

• JavaFX 2.0 SDK documentation online: http ://download.oracle.com /javafx/2.0/api/index.html

• JavaFX 2.0 CSS Reference Guide: http://download.oracle.com /javafx/2.0/api/javafx/scene/doc-files/cssref.html

• The w3schools.com CSS Tutorial: http://www.w3schools.com/css

Next post:

Previous post: