Lesson 8: Bringing Interactivity to GUI Elements
This section describes how to handle events in mobile and desktop applications by using the common profile of API. The application demonstrates an animated "Play-Pause" button that changes its appearance as you perform various mouse actions. Then, when you press or click the button, it fades. If you release the mouse button, its indicator changes from "Play" to "Pause." If you click the button again, the "Pause" indicator switches back to "Play." You can also drag and drop the button within the scene. Try the following applet to evaluate event handling. Press, release, and drag the button.
The following screen captures show all the possible button states.
Create a file with an .fx
extension, for example Events.fx
. Avoid using file names that match the names of existing classes, instance variables, or reserved words because this type of naming 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.
All button states are available in the following PNG images: play_onMouseExited.png
, play_onMousePressed.png
, stop_onMouseExited.png
, and stop_onMousePressed.png
. To use the images as scene objects, use a combination of the Image
and ImageView
classes.
- Add
import
statements for theImage
andImageView
classes. - Define four
Image
objects corresponding to different states of the button.
When specifying the imageurl
, you can set the URI of the resource or use the relative codebase. In this example, the imageurl
is set by using the__DIR__
variable that indicates the directory where the image is located. By default it points to the current directory, so ensure that the images are located in the same directory as application-compiled classes. To run the application on the mobile emulator ensure that the images are packed into the application jar file along with the compiled classes. - Define the
image
variable to store an image of the current button state, and set it to the initial state,playNormal
. - Define the
button
variable to the a scene object corresponding to the current state of the button, and bind it to the image variable. - Specify the scene of the application and add the button to its content.
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
def playNormal = Image { url: "{__DIR__}play_onMouseExited.png"};
def playPressed = Image { url: "{__DIR__}play_onMousePressed.png"};
def stopNormal = Image { url: "{__DIR__}stop_onMouseExited.png"};
def stopPressed = Image { url: "{__DIR__}stop_onMousePressed.png"};
var image = playNormal;
var button = ImageView {image: bind image}
Stage {
title: "Play Button"
scene: Scene {
width: 300
height: 240
content: Group {
content: button
}
}
}
Note: The button is added to the Group construct for further application enhancements. In your application you can add anImageView
object directly to the scene content..
This application handles three types of mouse events: mouse is pressed, mouse is released, and mouse is dragged. Each of these events is processed by a specific Node
function. Because the ImageView
class inherits all Node
instance variables and functions, you can apply the onMousePressed
, onMouseReleased
, and onMouseDragged
function to your button.
The press event happens when you press the button with a stylus or a mouse without releasing it. In this example, the press event changes the button's appearance.
To handle the mouse press event, perform the following steps.
- Define a Boolean variable named
state
to fix whether the button is in the Play or Stop mode. Set thetrue
value so that the button will be in Play mode when the application is started. - Define the
X
andY
variables to use them for calculating the button's position when processing the drag event. - Use the
if
construction to check the mode of the button. If it is in Play mode, the image is set toplayPressed
, andstopPressed
otherwise.var mode = true; //true for the Play mode,
//false for the Stop mode
var X: Number;
var Y: Number;
onMousePressed: function(event) {
X = event.sceneX - event.node.translateX;
Y = event.sceneY - event.node.translateY;
image = if (mode){
playPressed;
} else {
stopPressed;
};
}
As a result, the button changes its appearance when you press it depending on the mode of the button.
The release event occurs when you release a mouse pointer from the button. In this example, when you release the pointer from the button, it switches its mode.
To handle the mouse release event, use the following code:
onMouseReleased: function(event) { |
After an image is changed, the mode
variable changes its value to the opposite. At this point, the application implements switching between the Play and Stop modes and changing the button appearance on the mouse press. The next section concerns dragging the button within the scene.
Unlike the mouse events mentioned in the previous sections, the onMouseDragged
event does not change the button's appearance. This event enables you to alter the button position dragging it when the mouse is pressed. In this example, you cannot move the button beyond the bounds of the scene.
Use the following code fragment to handle the drag event:
onMouseDragged: function(event) { |
Two if
constructions are used to check whether the button has been dragged outside of the scene, and to set values for the translateX
and translateY
variables of the button. Consider an example when the drag event occurred at the point (320, 100). Suppose that the X
was fixed as 5, and the Y
was fixed as 10. Then the event.node.translateX - X
= 320 - 5 = 315, while 300 - image.width
= 300 -63 = 237. The value 315 is greater than 237, so the translateX
variable will be set to 300 - image.width
= 237, and the button will be placed at the right border of the scene. The translateY
variable will be set to event.sceneY
- Y = 100 - 10 = 90. Therefore, the button will be moved to the following position: translateX
= 237, translateY
= 90.
The following screen capture shows the application run on the Touch Phone emulator.
You can find the complete code of this application in the EventsCommon.fx
file. The next section discusses how to handle some additional desktop-specific events.
Desktop Profile
- | Adding Tooltips |
- | Handling the Mouse-Enter Event |
- | Handling the Mouse-Exit Event |
In this section, you will learn how to enhance the existing example by using additional features specific for desktop applications. Consider handling the mouse-enter and mouse-exit events by changing the button's appearance when the mouse pointer is on it. In addition, the modified application will show two variants of tooltips depending in the mode of the button. Try the following applet to evaluate event handling. Hover, press, release, and drag the button.
Two new images represent the button's state: play_onMouseEntered.png
and stop_onMouseEntered.png
. So you need to define two more Image
variables.
def playHover = Image { url: "{__DIR__}play_onMouseEntered.png"}; |
Perform the following steps to create a textual tooltip and add it to the scene.
- Add import statements for the
Text
,Font
,Timeline
, andColor
classes. - Declare a
Text
object specifying the string to render, the color, and the position of the tooltip. Set thecontent
variable depending on the current mode of the button. Set "Play Button" when the button is in Play mode, and "Stop Button" otherwise. Also bind thetranslateX
andtranslateY
variables to the corresponding variables of thebutton
object. - Add the
tooltip
object to the scene.import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.Group;
import javafx.animation.Timeline;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
var tooltip = Text {
content: bind if (mode) "Play Button" else "Stop Button"
translateX: bind button.translateX
translateY: bind button.translateY + 80
opacity: 0.0
font: Font {
size: 12
name: "Tahoma"
}
fill: Color.BLACK
};
Stage {
title: "Play Button"
scene: Scene {
fill: Color.WHITE
width: 300
height: 240
content: Group {
content: [button, tooltip]
}
}
This event happens when you position the mouse pointer in the button area. This event is controlled by the onMouseEntered
function.
To handle the mouse enter event define the onMouseEntered
function. Create a Timeline
object to alter the opacity of tooltips so that they do not appear instantly as you hover the button, but gradually within five seconds. The following code fragment performs these tasks.
def appear = Timeline { |
After you enter the button area with the mouse pointer, the playHover
or stopHover
image appears and an animation timeline starts adding the tooltip. For more information about the onMouseEntered
function, see JavaFX Script API. For more information about the MouseEvent
class, see JavaFX Script API. For more information about animation, see Creating Animated Objects.
Note: Because a new state was introduced, you need to apply the following code for theonMouseReleased
function. When the mouse is released the button should be in a hovered state, not in the initial state.
onMouseReleased: function(event) {
if (mode){
image = stopHover;
mode = false;
} else {
image = playHover;
mode = true;
}
}
This type of event occurs when the mouse pointer exits the button area. The event is defined by the onMouseExited
function.
To define the mouse-exit event, use the following code:
onMouseExited: function(event) { |
When the mouse pointer exits the area defined by the graphic button, the button's appearance returns to its initial state. The tooltip disappears, because the rate
variable of the animation timeline is set to -1
and the tooltip opacity alters from 1.0 to 0.0.
For more information about the onMouseExited
function, see JavaFX Script API.
Here is the complete Events.fx
file.
0 comments:
Post a Comment