Legal Terms and Copyright Notice
/*
* Copyright (c) 2012 Oracle and/or its affiliates.
* All rights reserved. Use is subject to license terms.
*
* This file is available and licensed under the following license:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package touchevents;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.effect.DropShadow;
import javafx.scene.effect.Lighting;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.TouchEvent;
import javafx.scene.input.TouchPoint;
import javafx.scene.paint.Color;
import javafx.scene.paint.CycleMethod;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
/**
*
* Sample that shows how touch events can be used. UI contains four folders
* and a row of blocks with a circle on one of the blocks. The folders
* can be moved independently by touching one or more simultaneously
* (number of folders that can be moved at one time can be limited by the
* number of touch points the screen supports).
* The circle can be moved from block to block by first touching the circle
* and then touching an empty block. Jumping can continue until the finger
* over the circle is removed.
*
*/
public class TouchEvents extends Application {
@Override
public void start(Stage primaryStage) {
Group root = new Group();
final TouchImage img1 = new TouchImage(50, 20,
new Image(TouchEvents.class.getResource(
"images/folder002.png").toExternalForm(), false));
final TouchImage img2 = new TouchImage(350, 20,
new Image(TouchEvents.class.getResource(
"images/folder004.png").toExternalForm(), false));
final TouchImage img3 = new TouchImage(150, 200,
new Image(TouchEvents.class.getResource(
"images/folder006.png").toExternalForm(), false));
final TouchImage img4 = new TouchImage(450, 200,
new Image(TouchEvents.class.getResource(
"images/folder007.png").toExternalForm(), false));
root.getChildren().addAll(img1, img2, img3, img4);
for (int i = 1; i <= 5; i++) {
Rectangle pad = new Rectangle(100, 85, Color.BLANCHEDALMOND);
pad.setTranslateX((i*125-100));
pad.setTranslateY(470);
pad.setStroke(Color.GRAY);
root.getChildren().add(pad);
}
root.getChildren().add(new Ball(75, 512));
Scene scene = new Scene(root, 650, 600);
scene.setFill(Color.GAINSBORO);
primaryStage.setTitle("Touch Events Example");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Image that can be dragged by a finger on a touch screen
*/
public static class TouchImage extends ImageView {
private long touchId = -1;
double touchx, touchy;
public TouchImage(int x, int y, Image img) {
super(img);
setTranslateX(x);
setTranslateY(y);
setEffect(new DropShadow(8.0, 4.5, 6.5, Color.DARKSLATEGRAY));
setOnTouchPressed(new EventHandler<TouchEvent>() {
@Override public void handle(TouchEvent event) {
if (touchId == -1) {
touchId = event.getTouchPoint().getId();
touchx = event.getTouchPoint().getSceneX() - getTranslateX();
touchy = event.getTouchPoint().getSceneY() - getTranslateY();
}
event.consume();
}
});
setOnTouchReleased(new EventHandler<TouchEvent>() {
@Override public void handle(TouchEvent event) {
if (event.getTouchPoint().getId() == touchId) {
touchId = -1;
}
event.consume();
}
});
setOnTouchMoved(new EventHandler<TouchEvent>() {
@Override public void handle(TouchEvent event) {
if (event.getTouchPoint().getId() == touchId) {
setTranslateX(event.getTouchPoint().getSceneX() - touchx);
setTranslateY(event.getTouchPoint().getSceneY() - touchy);
}
event.consume();
}
});
}
}
/**
* Ball that can jump from one rectangle to another by touching the
* ball on a touch screen with one finger and touching another rectangle
* with a second finger. As long as the finger currently over the ball is
* not lifted, the ball can be jumped again.
*/
private static class Ball extends Circle {
double touchx, touchy;
public Ball(int x, int y) {
super(35);
RadialGradient gradient = new RadialGradient(0.8, -0.5, 0.5, 0.5, 1,
true, CycleMethod.NO_CYCLE, new Stop [] {
new Stop(0, Color.FIREBRICK),
new Stop(1, Color.BLACK)
});
setFill(gradient);
setTranslateX(x);
setTranslateY(y);
setOnTouchPressed(new EventHandler<TouchEvent>() {
@Override public void handle(TouchEvent event) {
if (event.getTouchCount() == 1) {
touchx = event.getTouchPoint().getSceneX() - getTranslateX();
touchy = event.getTouchPoint().getSceneY() - getTranslateY();
setEffect(new Lighting());
}
event.consume();
}
});
setOnTouchReleased(new EventHandler<TouchEvent>() {
@Override public void handle(TouchEvent event) {
setEffect(null);
event.consume();
}
});
// Jump if the first finger touched the ball and is either
// moving or still, and the second finger touches a rectangle
EventHandler<TouchEvent> jumpHandler = new EventHandler<TouchEvent>() {
@Override public void handle(TouchEvent event) {
if (event.getTouchCount() != 2) {
// Ignore if this is not a two-finger touch
return;
}
TouchPoint main = event.getTouchPoint();
TouchPoint other = event.getTouchPoints().get(1);
if (other.getId() == main.getId()) {
// Ignore if the second finger is in the ball and
// the first finger is anywhere else
return;
}
if (other.getState() != TouchPoint.State.PRESSED ||
other.belongsTo(Ball.this) ||
!(other.getTarget() instanceof Rectangle) ){
// Jump only if the second finger was just
// pressed in a rectangle
return;
}
// Jump now
setTranslateX(other.getSceneX() - touchx);
setTranslateY(other.getSceneY() - touchy);
// Grab the destination touch point, which is now inside
// the ball, so that jumping can continue without
// releasing the finger
other.grab();
// The original touch point is no longer of interest, so
// call ungrab() to release the target
main.ungrab();
event.consume();
}
};
setOnTouchStationary(jumpHandler);
setOnTouchMoved(jumpHandler);
}
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Back to Document