L14-16 JavaFX
L14-16 JavaFX
2
            (c) Paul Fodor and Pearson Inc.
    GUI
 Graphical User Interface (GUI)
   provides user-friendly human interaction
 Building Java GUIs require use of frameworks:
     AWT
     Swing
     JavaFX (part of Java since JSE 8, 2014) includes:
       GUI components
       Event Programming
       Graphics
3
                       (c) Paul Fodor and Pearson Inc.
    How do GUIs work?
• They loop and respond to events
Render GUI
4
                    (c) Paul Fodor and Pearson Inc.
    Example: a mouse click on a button
     Operating System recognizes mouse click
      determines which window it was inside
      notifies that program
     Program runs in loop
      checks input buffer filled by OS
      if it finds a mouse click:
        determines which component in the program
        if the click was on a relevant component
           respond appropriately according to handler
5
                       (c) Paul Fodor and Pearson Inc.
    GUI Look vs. Behavior
     Look
     physical appearance
     custom component design
     containment
     layout management
     Behavior
     interactivity
     event programmed response
6
                  (c) Paul Fodor and Pearson Inc.
     What does a GUI framework do for you?
     Provides ready made visible, interactive,
     customizable components
      you wouldn’t want to have to code your own
       window
7
                       (c) Paul Fodor and Pearson Inc.
      JavaFX vs Swing and AWT
     Swing and AWT are replaced by the JavaFX platform for
      developing rich Internet applications in JDK8 (2014)
     History:
       When Java was introduced (1996), the GUI classes were bundled in a
        library known as the Abstract Windows Toolkit (AWT)
         AWT was prone to platform-specific bugs
         AWT was fine for developing simple graphical user interfaces, but not for
          developing comprehensive GUI projects
       The AWT user-interface components were replaced by a more robust,
        versatile, and flexible library known as Swing components (1997)
         Swing components are painted directly on canvases using Java code
         Swing components depend less on the target platform and use less of the native
          GUI resource
       With the release of Java 8, Swing is replaced by a
        completely new GUI platform: JavaFX
8
                                 (c) Paul Fodor and Pearson Inc.
                  Basic Structure of JavaFX
          Stage
        Scene
Button
     javafx.application.Application is
      the entry point for JavaFX applications
        JavaFX creates an application thread for running the
         application start method, processing input events,
         and running animation timelines.
        Override the start(Stage) method!
     javafx.stage.Stage is the top level JavaFX
      container.
          The primary Stage is constructed by the platform.
     javafx.scene.Scene class is the container
        for all content in a scene graph.
       javafx.scene.Node is the base class for
9       scene graph nodes.
                  (c) Paul Fodor and Pearson Inc.
     import   javafx.application.Application;
     import   javafx.stage.Stage;
     import   javafx.scene.Scene;
     import   javafx.scene.control.Button;
         /**
           * The main method is only needed for the IDE with limited
           * JavaFX support. Not needed for running from the command line.
           */
         public static void main(String[] args) {
            launch(args);
         }
     }
10
                              (c) Paul Fodor and Pearson Inc.
// Multiple stages can be added beside the primaryStage
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
12
            (c) Paul Fodor and Pearson Inc.
import    javafx.application.Application;
import    javafx.stage.Stage;
import    javafx.scene.Scene;
import    javafx.scene.layout.StackPane;
import    javafx.scene.control.Button;
13
                              (c) Paul Fodor and Pearson Inc.
     Display a Shape
14
                         (c) Paul Fodor and Pearson Inc.
import   javafx.application.Application;
import   javafx.stage.Stage;
import   javafx.scene.Scene;                                            Circle in a Pane
import   javafx.scene.layout.Pane;
import   javafx.scene.shape.Circle;
import   javafx.scene.paint.Color;
  /**
    * The main method is only needed for the IDE with limited
    * JavaFX support. Not needed for running from the command line.
    */
  public static void main(String[] args) {
     launch(args);
  }
}15
                                      (c) Paul Fodor and Pearson Inc.
     Binding Properties
      JavaFX introduces a new concept called binding property
       that enables a target object to be bound to a source object.
        If the value in the source object changes, the target property is
         also changed automatically.
        The target object is simply called a binding object or a binding
         property.
      Resizing the window in the previous example would cover
       the object:
16
                            (c) Paul Fodor and Pearson Inc.
     import    javafx.application.Application;
     import    javafx.stage.Stage;
     import    javafx.scene.Scene;
     import    javafx.scene.layout.Pane;
     import    javafx.scene.shape.Circle;
     import    javafx.scene.paint.Color;
         /**
           * The main method is only needed for the IDE with limited
           * JavaFX support. Not needed for running from the command line.
           */
         public static void main(String[] args) {
            launch(args);
17       }
     }                                  (c) Paul Fodor and Pearson Inc.
         JavaFX Beans and Binding
• Changes made to one object will automatically be reflected in another object
     • A graphical user interface automatically keeps its display synchronized
       with the application's underlying data: a binding observes its list of
       dependencies for changes, and then updates itself automatically after a
       change has been detected.
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
         /**
          * The main method is only needed for the IDE with limited
          * JavaFX support. Not needed for running from the command line.
          */
         public static void main(String[] args) {
           launch(args);
19       }
                                (c) Paul Fodor and Pearson Inc.
     }
     JavaFX CSS style and Node rotation
     import   javafx.application.Application;
     import   javafx.stage.Stage;
     import   javafx.scene.Scene;
     import   javafx.scene.layout.StackPane;
     import   javafx.scene.control.Button;
20
                                (c) Paul Fodor and Pearson Inc.
     JavaFX External CSS style file
  // Example to load and use a CSS style file in a scene
  import javafx.application.Application;
  import javafx.stage.Stage;
  import javafx.scene.Scene;
  import javafx.scene.layout.BorderPane;
22
            (c) Paul Fodor and Pearson Inc.
 Helper classes: The Font Class
23
             (c) Paul Fodor and Pearson Inc.
The Image and ImageView Classes
24
           (c) Paul Fodor and Pearson Inc.
     import   javafx.application.Application;
     import   javafx.stage.Stage;
     import   javafx.scene.Scene;
     import   javafx.scene.layout.Pane;
     import   javafx.scene.layout.HBox;
     import   javafx.scene.image.Image;
     import   javafx.scene.image.ImageView;
     import   javafx.geometry.Insets;
26
                         (c) Paul Fodor and Pearson Inc.
 FlowPane
27
            (c) Paul Fodor and Pearson Inc.
     import javafx.application.Application;
     import javafx.stage.Stage;
     import javafx.scene.Scene;
     import javafx.scene.layout.FlowPane;
     import javafx.scene.control.Label;
     import javafx.scene.control.TextField;
     import javafx.geometry.Insets;
     public class ShowFlowPane extends Application {
       @Override
       public void start(Stage primaryStage) {
         FlowPane pane = new FlowPane();
         pane.setPadding(new Insets(11, 12, 13, 14));
         pane.setHgap(5);
         pane.setVgap(5);
         // Place nodes in the pane
         pane.getChildren().addAll(new Label("First Name:"),
           new TextField(), new Label("MI:"));
         TextField tfMi = new TextField();
         tfMi.setPrefColumnCount(1);
         pane.getChildren().addAll(tfMi, new Label("Last Name:"),
           new TextField());
         // Create a scene and place it in the stage
         Scene scene = new Scene(pane, 210, 150);
         primaryStage.setTitle("ShowFlowPane");
         primaryStage.setScene(scene); // Place the scene in the stage
         primaryStage.show(); // Display the stage
       }
         public static void main(String[] args) {
         launch(args);
28     }
                              (c) Paul Fodor and Pearson Inc.
     }
 GridPane
29
            (c) Paul Fodor and Pearson Inc.
     import javafx.application.Application;
     import javafx.stage.Stage;
     import javafx.scene.Scene;
     import javafx.scene.layout.GridPane;
     import javafx.scene.control.*;
     import javafx.geometry.*;
     public class ShowGridPane extends Application {
       @Override
       public void start(Stage primaryStage) {
         // Create a pane and set its properties
         GridPane pane = new GridPane();
         pane.setAlignment(Pos.CENTER);
         pane.setHgap(5.5);
         pane.setVgap(5.5);
         // Place nodes in the pane at positions               column,row
         pane.add(new Label("First Name:"), 0, 0);
         pane.add(new TextField(), 1, 0);
         pane.add(new Label("MI:"), 0, 1);
         pane.add(new TextField(), 1, 1);
         pane.add(new Label("Last Name:"), 0, 2);
         pane.add(new TextField(), 1, 2);
         Button btAdd = new Button("Add Name");
         pane.add(btAdd, 1, 3);
         GridPane.setHalignment(btAdd, HPos.RIGHT);
         // Create a scene and place it in the stage
         Scene scene = new Scene(pane);
         primaryStage.setTitle("ShowGridPane");
         primaryStage.setScene(scene); primaryStage.show(); }
       public static void main(String[] args) {
30       launch(args);
                               (c) Paul Fodor and Pearson Inc.
       }}
BorderPane
31
        (c) Paul Fodor and Pearson Inc.
     import javafx.application.Application;
     import javafx.stage.Stage;
     import javafx.scene.Scene;
     import javafx.scene.layout.BorderPane;
     import javafx.scene.layout.StackPane;
     import javafx.scene.control.Label;
     import javafx.geometry.Insets;
     public class ShowBorderPane extends Application {
       @Override
       public void start(Stage primaryStage) {
         BorderPane pane = new BorderPane();
         pane.setTop(new CustomPane("Top"));
         pane.setRight(new CustomPane("Right"));
         pane.setBottom(new CustomPane("Bottom"));
         pane.setLeft(new CustomPane("Left"));
         pane.setCenter(new CustomPane("Center"));
         Scene scene = new Scene(pane);
         primaryStage.setScene(scene); primaryStage.show();
       }
       public static void main(String[] args) {
         launch(args);
       }
     }
     class CustomPane extends StackPane {
       public CustomPane(String title) {
         getChildren().add(new Label(title));
         setStyle("-fx-border-color: red");
         setPadding(new Insets(11.5, 12.5, 13.5, 14.5));
       }
32   }
                              (c) Paul Fodor and Pearson Inc.
Hbox and VBox
33
        (c) Paul Fodor and Pearson Inc.
     import javafx.application.Application;
     import javafx.stage.Stage;
     import javafx.scene.Scene;
     import javafx.scene.layout.BorderPane;
     import javafx.scene.layout.HBox;
     import javafx.scene.layout.VBox;
     import javafx.scene.control.Button;
     import javafx.scene.control.Label;
     import javafx.scene.image.Image;
     import javafx.scene.image.ImageView;
     public class ShowHBoxVBox extends Application {
       @Override
       public void start(Stage primaryStage) {
         BorderPane pane = new BorderPane();
         HBox hBox = new HBox(15);
         hBox.setStyle("-fx-background-color: gold");
         hBox.getChildren().add(new Button("Computer Science"));
         hBox.getChildren().add(new Button("CEWIT"));
         ImageView imageView = new ImageView(new Image("cs14.jpg"));
         hBox.getChildren().add(imageView);
         pane.setTop(hBox);
         VBox vBox = new VBox(15);
         vBox.getChildren().add(new Label("Courses"));
         Label[] courses = {new Label("CSE114"), new Label("CSE214"),
             new Label("CSE219"), new Label("CSE308")};
         for (Label course: courses) {
           vBox.getChildren().add(course);
         }
         pane.setLeft(vBox);
34       Scene scene = new Scene(pane); primaryStage.setScene(scene);
         primaryStage.show(); (c) Paul Fodor and Pearson Inc.
     Shapes
JavaFX provides many shape classes for drawing texts,
lines, circles, rectangles, ellipses, arcs, polygons, and
polylines.
35
                       (c) Paul Fodor and Pearson Inc.
     Text
36
            (c) Paul Fodor and Pearson Inc.
     import javafx.application.Application;
     import javafx.stage.Stage;
     import javafx.scene.Scene;
     import javafx.scene.layout.Pane;
     import javafx.scene.paint.Color;
     import javafx.geometry.Insets;
     import javafx.scene.text.Text;
     import javafx.scene.text.Font;
     import javafx.scene.text.FontWeight;
     import javafx.scene.text.FontPosture;
     public class ShowText extends Application {
       @Override
       public void start(Stage primaryStage) {
         Pane pane = new Pane();
         pane.setPadding(new Insets(5, 5, 5, 5));
         Text text1 = new Text(20, 20, "Programming is fun");
         text1.setFont(Font.font("Courier", FontWeight.BOLD,
           FontPosture.ITALIC, 15));
         pane.getChildren().add(text1);
         Text text2 = new Text(60, 60, "Programming is fun\nDisplay text");
         pane.getChildren().add(text2);
         Text text3 = new Text(10, 100, "Programming is fun\nDisplay text");
         text3.setFill(Color.RED);
         text3.setUnderline(true);
         text3.setStrikethrough(true);
         pane.getChildren().add(text3);
         Scene scene = new Scene(pane, 600, 800);
         primaryStage.setScene(scene); primaryStage.show();
       }
37   ...
     }                        (c) Paul Fodor and Pearson Inc.
     Line
38
            (c) Paul Fodor and Pearson Inc.
     import javafx.application.Application;
     import javafx.stage.Stage;
     import javafx.scene.Scene;
     import javafx.scene.layout.Pane;
     import javafx.scene.shape.Line;
     import javafx.scene.paint.Color;
     public class ShowLine extends Application {
         @Override
         public void start(Stage primaryStage) {
             Pane pane = new Pane();
             Line line1 = new Line(10, 10, 10, 10);
             line1.endXProperty().bind(pane.widthProperty().subtract(10));
             line1.endYProperty().bind(pane.heightProperty().subtract(10));
             line1.setStrokeWidth(5);
             line1.setStroke(Color.GREEN);
             pane.getChildren().add(line1);
             Line line2 = new Line(10, 10, 10, 10);
             line2.startXProperty().bind(pane.widthProperty().subtract(10));
             line2.endYProperty().bind(pane.heightProperty().subtract(10));
             line2.setStrokeWidth(5);
             line2.setStroke(Color.GREEN);
             pane.getChildren().add(line2);
             Scene scene = new Scene(pane, 200, 200);
             primaryStage.setScene(scene);
             primaryStage.show();
         }
         public static void main(String[] args) {
             launch(args);
         }
39   }
                              (c) Paul Fodor and Pearson Inc.
     Rectangle
40
             (c) Paul Fodor and Pearson Inc.
     import javafx.application.Application;
     import javafx.stage.Stage;
     import javafx.scene.Scene;
     import javafx.scene.layout.Pane;
     import javafx.scene.text.Text;
     import javafx.scene.shape.Rectangle;
     import javafx.scene.paint.Color;
     import java.util.Collections;
     public class ShowRectangle extends Application {
       public void start(Stage primaryStage) {
         Pane pane = new Pane();
         Rectangle r1 = new Rectangle(25, 10, 60, 30);
         r1.setStroke(Color.BLACK);
         r1.setFill(Color.WHITE);
         pane.getChildren().add(new Text(10, 27, "r1"));
         pane.getChildren().add(r1);
         Rectangle r2 = new Rectangle(25, 50, 60, 30);
         pane.getChildren().add(new Text(10, 67, "r2"));
         pane.getChildren().add(r2);
         for (int i = 0; i < 4; i++) {
           Rectangle r = new Rectangle(100, 50, 100, 30);
           r.setRotate(i * 360 / 8);
           r.setStroke(Color.color(Math.random(), Math.random(),
               Math.random()));
           r.setFill(Color.WHITE);
           pane.getChildren().add(r);
        }
        Scene scene = new Scene(pane, 250, 150);
        primaryStage.setScene(scene); primaryStage.show();
41    }
      ...// main              (c) Paul Fodor and Pearson Inc.
 Circle
42
          (c) Paul Fodor and Pearson Inc.
     Ellipse
     radiusX   radiusY
                                (centerX, centerY)
43
               (c) Paul Fodor and Pearson Inc.
 Arc   radiusY                                       length
startAngle
0 degree
       radiusX
                                                   (centerX, centerY)
44
                 (c) Paul Fodor and Pearson Inc.
      Polygon and Polyline
                                   The getter and setter methods for property values and a getter for property
      javafx.scene.shape.Polygon   itself are provided in the class, but omitted in the UML diagram for brevity.
 45
                                     (c) Paul Fodor and Pearson Inc.
      Event Programming
      Procedural programming is executed in
       procedural/statement order
      In event-driven programming, code is executed
       upon activation of events
      Operating Systems constantly monitor events
        Ex: keystrokes, mouse clicks, etc…
      The OS:
        sorts out these events
        reports them to the appropriate programs
46
                     (c) Paul Fodor and Pearson Inc.
      Where do we come in?
      For each control (button, combo box, etc.):
      define an event handler
      construct an instance of event handler
      tell the control who its event handler is
      Event Handler?
      code with response to event
      a.k.a. event listener
47
                    (c) Paul Fodor and Pearson Inc.
     Java’s Event Handling
      An event source is a GUI control
        JavaFX: Button, ChoiceBox, ListView, etc.
          http://docs.oracle.com/javase/8/javafx/user-interface-tutorial/ui_controls.htm
        different types of sources:
          can detect different types of events
          can register different types of listeners (handlers)
48
                                 (c) Paul Fodor and Pearson Inc.
      Java’s Event Handling
      When the user interacts with a control
      (source):
       an event object is constructed
       the event object is sent to all registered listener
        objects
       the listener object (handler) responds as you
        defined it to
49
                       (c) Paul Fodor and Pearson Inc.
      Event Listeners (Event Handler)
      Defined by you, the application programmer
      you customize the response
      How?
         Inheritance & Polymorphism
      You define your own listener class
      implement the appropriate interface
      define responses in all necessary methods
50
                     (c) Paul Fodor and Pearson Inc.
        Event Objects
      Contain information about the event
      Like what?
       location of mouse click
       event source that was interacted with
       etc.
      Listeners use them to properly respond
       different methods inside a listener object can
        react differently to different types of interactions
51
                        (c) Paul Fodor and Pearson Inc.
import   javafx.application.Application;
import   javafx.stage.Stage;
import   javafx.scene.Scene;
import   javafx.scene.layout.HBox;
import   javafx.scene.control.Button;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
public class HandleEvent extends Application {
 public void start(Stage primaryStage) {
        HBox pane = new HBox(10);
        Button btOK = new Button("OK");
        Button btCancel = new Button("Cancel");
        OKHandlerClass handler1 = new OKHandlerClass();
        btOK.setOnAction(handler1);
        CancelHandlerClass handler2 = new CancelHandlerClass();
        btCancel.setOnAction(handler2);
        pane.getChildren().addAll(btOK, btCancel);
        Scene scene = new Scene(pane);
        primaryStage.setScene(scene); primaryStage.show();
 }…/*main*/}
class OKHandlerClass implements EventHandler<ActionEvent> {
    @Override
    public void handle(ActionEvent e) {
        System.out.println("OK button clicked");
    }}
class CancelHandlerClass implements EventHandler<ActionEvent> {
    @Override
    public void handle(ActionEvent e) {
 52     System.out.println("Cancel    button       clicked");
                                (c) Paul Fodor and Pearson Inc.
    }}
      Handling GUI Events
 Source object: button.
   An event is generated by external user actions such as mouse movements,
    mouse clicks, or keystrokes.
 An event can be defined as a type of signal to the program that
  something has happened.
 Listener object contains a method for processing the event.
53
                            (c) Paul Fodor and Pearson Inc.
     Event Classes
54
             (c) Paul Fodor and Pearson Inc.
      Event Information
  An event object contains whatever properties are
     pertinent to the event:
      the source object of the event using the
    getSource() instance method in the
    EventObject class.
  The subclasses of EventObject deal with
     special types of events, such as button actions,
     window events, component events, mouse
     movements, and keystrokes.
55
                        (c) Paul Fodor and Pearson Inc.
 Selected User Actions and Handlers
56
             (c) Paul Fodor and Pearson Inc.
     The Delegation Model
57
             (c) Paul Fodor and Pearson Inc.
ControlCircle program that uses two buttons to control the size of a circle
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.control.Button;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.paint.Color;                                  ...
import javafx.scene.shape.Circle;
public class ControlCircle extends Application {
    private CirclePane circlePane = new CirclePane();
    @Override
    public void start(Stage primaryStage) {
        HBox hBox = new HBox();
        Button btEnlarge = new Button("Enlarge");
        Button btShrink = new Button("Shrink");
        hBox.getChildren().add(btEnlarge);
        hBox.getChildren().add(btShrink);
        btEnlarge.setOnAction(new EnlargeHandler());
        BorderPane borderPane = new BorderPane();
        borderPane.setCenter(circlePane);
        borderPane.setBottom(hBox);
        BorderPane.setAlignment(hBox, Pos.CENTER);
        Scene scene = new Scene(borderPane, 200, 150);
 58     primaryStage.setScene(scene); primaryStage.show();
    }                           (c) Paul Fodor and Pearson Inc.
ControlCircle program that uses two buttons to control the size of a circle
       // Inner Class
       class EnlargeHandler
           implements EventHandler<ActionEvent> {
           @Override
           public void handle(ActionEvent e) {
               circlePane.enlarge();
           }
       }
   }
   class CirclePane extends StackPane {
       private Circle circle = new Circle(50);
       public CirclePane() {
           getChildren().add(circle);
           circle.setStroke(Color.BLACK);
           circle.setFill(Color.WHITE);
       }
       public void enlarge() {
           circle.setRadius(circle.getRadius() + 2);
       }
       public void shrink() {
           circle.setRadius(circle.getRadius() > 2
                   ? circle.getRadius() - 2 : circle.getRadius());
59
       }
   }                      (c) Paul Fodor and Pearson Inc.
       Inner Class Listeners
 A listener class is designed specifically to
     create a listener object for a GUI component
     (e.g., a button).
     Any object instance of the inner handler class
       has access to all GUI fields of the outer class.
     It will not be shared by other applications.
60
                      (c) Paul Fodor and Pearson Inc.
       Inner Classes
 public class OuterClass {                               The InnerClass is a
   private int data = 0;                                    member of OuterClass
   OuterClass(){
     InnerClass y = new InnerClass();                        An inner class can
     y.m2();                                                  reference the data and
   }
   public void m1() {
                                                              methods defined in the
     data++;                                                  outer class in which it
   }                                                          nests, so you do not need
   public static void main(String[] args) {
     OuterClass x = new OuterClass();                         to pass the reference of the
     System.out.println(x.data);                              outer class to the
   }
   class InnerClass {
                                                              constructor of the inner
     public void m2() {                                       class.
       /* Directly reference data and                        An inner class is compiled
         method defined in outer class */
       data++;                                                into a class named
       m1();                                              OuterClass$InnerClass.class
     }
61 }
                          (c) Paul Fodor and Pearson Inc.
 }
      Inner Classes
  An inner class can be declared public,
   protected, or private subject to the same
   visibility rules applied to a member of the class.
  An inner class can be declared static:
      The static inner class can be accessed using the
       outer class name,
      However, a static inner class cannot access
       nonstatic members of the outer class.
62
                      (c) Paul Fodor and Pearson Inc.
       Anonymous Inner Classes
  Inner class listeners can be shortened using anonymous
     inner classes: inner classes without a name.
      It combines declaring an inner class and creating an instance of
      the class in one step.
  An anonymous inner class is declared as follows:
new SuperClassName/InterfaceName() {
 // Implement or override methods in superclass/interface
 // Other methods if necessary
}
63
                               (c) Paul Fodor and Pearson Inc.
        Anonymous Inner Classes
 An anonymous inner class must always extend a superclass or
     implement an interface, but it cannot have an explicit extends or
     implements clause.
    An anonymous inner class must implement all the abstract methods in
     the superclass or in the interface.
    An anonymous inner class always uses the no-arg constructor from its
     superclass to create an instance.
    If an anonymous inner class implements an interface, the constructor
     is Object().
    An anonymous inner class is compiled into a class named
     OuterClassName$n.class, where n is the count of inner
     classes.
64
                             (c) Paul Fodor and Pearson Inc.
     Anonymous Inner Classes
65
             (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.control.Button;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
public class AnonymousHandlerDemo extends Application {
    public void start(Stage primaryStage) {
        HBox hBox = new HBox();
        Button btNew = new Button("New");
        Button btOpen = new Button("Open"); //btSave, btPrint btns.
        hBox.getChildren().addAll(btNew, btOpen);
        // Create and register the handler
        btNew.setOnAction(new EventHandler<ActionEvent>() {
            @Override // Override the handle method
            public void handle(ActionEvent e) {
                System.out.println("Process New");
            }
        });
        btOpen.setOnAction(new EventHandler<ActionEvent>() {
            @Override // Override the handle method
            public void handle(ActionEvent e) {
                System.out.println("Process Open");
66          }
                           (c) Paul Fodor and Pearson Inc.
        });
        Scene scene = new Scene(hBox, 300, 50);
        primaryStage.setTitle("AnonymousHandlerDemo");
        primaryStage.setScene(scene);
        primaryStage.show();
     }
     public static void main(String[] args) {
         launch(args);
     }
}
67
                      (c) Paul Fodor and Pearson Inc.
 Simplifying Event Handing Using
 Lambda Expressions
 Lambda expression is a new feature in Java 8.
   Predefined functions for the type of the input.
 Lambda expressions can be viewed as an anonymous method
     with a concise syntax.
(a) Anonymous inner class event handler (b) Lambda expression event handler
68
                                        (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.scene.control.Button;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
public class LambdaHandlerDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
        // Hold two buttons in an HBox
        HBox hBox = new HBox();
        hBox.setSpacing(10);
        hBox.setAlignment(Pos.CENTER);
        Button btNew = new Button("New");
        Button btOpen = new Button("Open");
        Button btSave = new Button("Save");
        Button btPrint = new Button("Print");
        hBox.getChildren().addAll(btNew, btOpen, btSave, btPrint);
        btNew.setOnAction(e -> {System.out.println("Process New");});
        btOpen.setOnAction(e -> {System.out.println("Process Open");});
        btSave.setOnAction(e -> {System.out.println("Process Save");});
        btPrint.setOnAction(e -> {System.out.println("Process Print");});
        Scene scene = new Scene(hBox, 300, 50);
        primaryStage.setScene(scene);                              Output:
        primaryStage.show();                                       Process New
    }                                                              Process Open
    public static void main(String[] args) {
 69     launch(args); }}                                           Process Save
                                (c) Paul Fodor and Pearson Inc.
                                                                   Process Print
Basic Syntax for a Lambda Expression
 The basic syntax for a lambda expression is either:
 (type1 param1, type2 param2, ...) -> expression
or
 (type1 param1, type2 param2, ...) -> { statements; }
70
                         (c) Paul Fodor and Pearson Inc.
Single Abstract Method Interface (SAM)
 The statements in the lambda expression is all for
 that method.
 If it contains multiple methods, the compiler will
   not be able to compile the lambda expression.
 So, for the compiler to understand lambda
   expressions, the interface must contain exactly
   one abstract method.
 Such an interface is known as a functional interface,
   or a Single Abstract Method (SAM) interface.
71
                    (c) Paul Fodor and Pearson Inc.
 Loan Calculator
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.geometry.Pos;
import javafx.geometry.HPos;
public class LoanCalculator extends Application {
    private TextField tfAnnualInterestRate = new TextField();
    private TextField tfNumberOfYears = new TextField();
    private TextField tfLoanAmount = new TextField();
    private TextField tfMonthlyPayment = new TextField();
    private TextField tfTotalPayment = new TextField();
    private Button btCalculate = new Button("Calculate");
    @Override
    public void start(Stage primaryStage) {
        // Create UI
        GridPane gridPane = new GridPane();
        gridPane.setHgap(5);
        gridPane.setVgap(5);
        gridPane.add(new Label("Annual Interest Rate:"), 0, 0);
        gridPane.add(tfAnnualInterestRate, 1, 0);
        gridPane.add(new Label("Number of Years:"), 0, 1);
        gridPane.add(tfNumberOfYears, 1, 1);
        gridPane.add(new Label("Loan Amount:"), 0, 2);
        gridPane.add(tfLoanAmount, 1, 2);
        gridPane.add(new Label("Monthly Payment:"), 0, 3);
        gridPane.add(tfMonthlyPayment, 1, 3);
        gridPane.add(new Label("Total Payment:"), 0, 4);
72      gridPane.add(tfTotalPayment, 1, 4);
        gridPane.add(btCalculate, 1, (c)5);
                                         Paul Fodor and Pearson Inc.
       btCalculate.setOnAction(e -> calculateLoanPayment());
       Scene scene = new Scene(gridPane, 400, 250);
       primaryStage.setScene(scene);
       primaryStage.show();
   }
   private void calculateLoanPayment() {
       // Get values from text fields
       double interest = Double.parseDouble(tfAnnualInterestRate.getText());
       int year = Integer.parseInt(tfNumberOfYears.getText());
       double loanAmount = Double.parseDouble(tfLoanAmount.getText());
       // Create a loan object
       Loan loan = new Loan(interest, year, loanAmount);
       // Display monthly payment and total payment
       tfMonthlyPayment.setText(String.format("$%.2f", loan.getMonthlyPayment()));
       tfTotalPayment.setText(String.format("$%.2f", loan.getTotalPayment()));
   }
   public static void main(String[] args) {
       launch(args);
   }
}
class Loan implements java.io.Serializable {
    private double annualInterestRate;
    private int numberOfYears;
    private double loanAmount;
    private java.util.Date loanDate;
    public Loan(double annualInterestRate, int numberOfYears, double loanAmount) {
        this.annualInterestRate = annualInterestRate;
        this.numberOfYears = numberOfYears;
        this.loanAmount = loanAmount;
        loanDate = new java.util.Date();
    }
    public double getAnnualInterestRate() {
        return annualInterestRate;
    }
    public void setAnnualInterestRate(double annualInterestRate) {
73      this.annualInterestRate = annualInterestRate;
                                     (c) Paul Fodor and Pearson Inc.
    }
     public int getNumberOfYears() {
         return numberOfYears;
     }
     public void setNumberOfYears(int numberOfYears) {
         this.numberOfYears = numberOfYears;
     }
     public double getLoanAmount() {
         return loanAmount;
     }
     public void setLoanAmount(double loanAmount) {
         this.loanAmount = loanAmount;
     }
     public double getMonthlyPayment() {
         double monthlyInterestRate = annualInterestRate / 1200;
         double monthlyPayment = loanAmount * monthlyInterestRate / (1
                 - (Math.pow(1 / (1 + monthlyInterestRate), numberOfYears * 12)));
         return monthlyPayment;
     }
     public double getTotalPayment() {
         double totalPayment = getMonthlyPayment() * numberOfYears * 12;
         return totalPayment;
     }
     public java.util.Date getLoanDate() {
         return loanDate;
     }
}
74
                                     (c) Paul Fodor and Pearson Inc.
     MouseEvent
75
            (c) Paul Fodor and Pearson Inc.
// Move the text with the mouse clicked
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.text.Text;
public class MouseEventDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Text text = new Text(20, 20, "Programming is fun");
        pane.getChildren().add(text);
        text.setOnMouseDragged(e -> {
            text.setX(e.getX());
            text.setY(e.getY());
        });
        Scene scene = new Scene(pane, 300, 100);
        primaryStage.setTitle("MouseEventDemo");
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
76  }                   (c) Paul Fodor and Pearson Inc.
}
     The KeyEvent Class
77
             (c) Paul Fodor and Pearson Inc.
     import javafx.application.Application;
     import javafx.stage.Stage;
     import javafx.scene.Scene;
     import javafx.scene.layout.Pane;
     import javafx.scene.text.Text;
     public class KeyEventDemo extends Application {
       @Override
       public void start(Stage primaryStage) {
         Pane pane = new Pane();
         Text text = new Text(20, 20, "A");
         text.setFocusTraversable(true);
         pane.getChildren().add(text);
         text.setOnKeyPressed(e -> {
           switch (e.getCode()) {
             case DOWN: text.setY(text.getY() + 10); break;
             case UP: text.setY(text.getY() - 10); break;
             case LEFT: text.setX(text.getX() - 10); break;
             case RIGHT: text.setX(text.getX() + 10); break;
             default:
               if (Character.isLetterOrDigit(e.getText().charAt(0)))
                 text.setText(e.getText());
           }
         });
         Scene scene = new Scene(pane, 200, 200);
         primaryStage.setTitle("KeyEventDemo");
         primaryStage.setScene(scene);
         primaryStage.show();
       }
       public static void main(String[] args) {
           launch(args);
78
       }                        (c) Paul Fodor and Pearson Inc.
     }
     The KeyCode Constants
79
             (c) Paul Fodor and Pearson Inc.
import
       Control Circle with Mouse and Key
          javafx.application.Application;
import    javafx.geometry.Pos;
import    javafx.scene.Scene;
import    javafx.scene.control.Button;
import    javafx.scene.input.KeyCode;
import    javafx.scene.input.MouseButton;
import    javafx.scene.layout.HBox;
import    javafx.scene.layout.BorderPane;
import    javafx.stage.Stage;
         circlePane.setOnMouseClicked(e -> {
           if (e.getButton() == MouseButton.PRIMARY) {
             circlePane.enlarge();
           }
           else if (e.getButton() == MouseButton.SECONDARY) {
             circlePane.shrink();
           }
         });
         scene.setOnKeyPressed(e -> {
           if (e.getCode() == KeyCode.UP) {
             circlePane.enlarge();
           }
           else if (e.getCode() == KeyCode.DOWN) {
             circlePane.shrink();
           }
         });
     }
82
                              (c) Paul Fodor and Pearson Inc.
Listeners for Observable Objects
import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
public class ObservablePropertyDemo {
  public static void main(String[] args) {
    DoubleProperty balance = new SimpleDoubleProperty();
    balance.addListener(new InvalidationListener() {
      public void invalidated(Observable ov) {
        System.out.println("The new value is " +
          balance.doubleValue());
      }
    });
    balance.set(4.5);
  }
}
                                                       Output:
83
                     (c) Paul Fodor and Pearson Inc.
                                                       The new value is 4.5
Animation
 JavaFX provides the Animation class with the core
     functionality for all animations:
84
                          (c) Paul Fodor and Pearson Inc.
PathTransition
85
           (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Circle;
import javafx.animation.PathTransition;
import javafx.animation.Timeline;
import javafx.util.Duration;
public class PathTransitionDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Rectangle rectangle = new Rectangle(0, 0, 25, 50);
        rectangle.setFill(Color.ORANGE);
        Circle circle = new Circle(125, 100, 50);
        circle.setFill(Color.WHITE);
        circle.setStroke(Color.BLACK);
        pane.getChildren().addAll(circle,rectangle);
        // Create a path transition
        PathTransition pt = new PathTransition();
        pt.setDuration(Duration.millis(4000));
        pt.setPath(circle);
86      pt.setNode(rectangle);
                         (c) Paul Fodor and Pearson Inc.
         pt.setOrientation(
           PathTransition.OrientationType.
             ORTHOGONAL_TO_TANGENT);
         pt.setCycleCount(Timeline.INDEFINITE);
         pt.setAutoReverse(true);
         pt.play(); // Start animation
         circle.setOnMousePressed(e -> pt.pause());
         circle.setOnMouseReleased(e -> pt.play());
         Scene scene = new Scene(pane, 250, 200);
         primaryStage.setTitle("PathTransitionDemo");
         primaryStage.setScene(scene);
         primaryStage.show();
    }
    public static void
             main(String[] args){
        launch(args);
    }
    87
}                        (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Line;
import javafx.animation.PathTransition;
import javafx.scene.image.ImageView;
import javafx.util.Duration;
public class FlagRisingAnimation extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        ImageView imageView = new ImageView("us.jpg");
        pane.getChildren().add(imageView);
        PathTransition pt = new PathTransition(
             Duration.millis(10000),
               new Line(100, 200, 100, 0),
             imageView);
        pt.setCycleCount(5);
        pt.play(); // Start animation
        Scene scene = new Scene(pane, 250, 200);
88      primaryStage.setScene(scene); primaryStage.show();
                       (c) Paul Fodor and Pearson Inc.
    }
     FadeTransition
The FadeTransition class animates the change of the
opacity in a node over a given time:
89
                    (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Ellipse;
import javafx.animation.FadeTransition;
import javafx.animation.Timeline;
import javafx.util.Duration;
public class FadeTransitionDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
        Pane pane = new Pane();
        Ellipse ellipse = new Ellipse(10, 10, 100, 50);
        ellipse.setFill(Color.RED);
        ellipse.setStroke(Color.BLACK);
        ellipse.centerXProperty().bind(pane.widthProperty().divide(2));
        ellipse.centerYProperty().bind(pane.heightProperty().divide(2));
        ellipse.radiusXProperty().bind(pane.widthProperty().multiply(0.4));
        ellipse.radiusYProperty().bind(pane.heightProperty().multiply(0.4));
        pane.getChildren().add(ellipse);
        // Apply a fade transition to ellipse
        FadeTransition ft = new FadeTransition(Duration.millis(3000), ellipse);
        ft.setFromValue(1.0);
        ft.setToValue(0.1);
        ft.setCycleCount(Timeline.INDEFINITE);
        ft.setAutoReverse(true);
        ft.play(); // Start animation
        // Control animation
90      ellipse.setOnMousePressed(e -> ft.pause());
                                (c) Paul Fodor and Pearson Inc.
        ellipse.setOnMouseReleased(e -> ft.play());
        // Create a scene and place it in the stage
        Scene scene = new Scene(pane, 200, 150);
        primaryStage.setTitle("FadeTransitionDemo"); // Set the stage title
        primaryStage.setScene(scene); // Place the scene in the stage
        primaryStage.show(); // Display the stage
    }
91
                                   (c) Paul Fodor and Pearson Inc.
       Timeline
      PathTransition and FadeTransition
       define specialized animations.
      The javafx.animation.Timeline class
       can be used to program any animation using one
       or more javafx.animation.KeyFrames
       KeyFrame defines target values at a specified point
        in time for a set of variables that are interpolated along
        a Timeline.
         Each KeyFrame is executed sequentially at a specified
          time interval.
       Timeline inherits from Animation.
92
                           (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.util.Duration;
public class TimelineDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
        StackPane pane = new StackPane();
        Text text = new Text(20, 50, "Programming if fun");
        text.setFill(Color.RED);
        pane.getChildren().add(text);
        // Create a handler for changing text
        EventHandler<ActionEvent> eH = e -> {
            if (text.getText().length() != 0) {
                text.setText("");
            } else {
                text.setText("Programming is fun");
            }
        };
        Timeline animation = new Timeline(new KeyFrame(Duration.millis(500), eH));
        animation.setCycleCount(Timeline.INDEFINITE);
        // Start animation
93
        animation.play();      (c) Paul Fodor and Pearson Inc.
         // Pause and resume animation
         text.setOnMouseClicked(e -> {
             if (animation.getStatus() ==
                           Animation.Status.PAUSED) {
                 animation.play();
             } else {
                 animation.pause();
             }
         });
         Scene scene = new Scene(pane, 250, 50);
         primaryStage.setTitle("TimelineDemo");
         primaryStage.setScene(scene);
         primaryStage.show();
     }
94
                                (c) Paul Fodor and Pearson Inc.
 import javafx.application.Application;
 import javafx.stage.Stage;
 import javafx.animation.KeyFrame;                               Clock Animation
 import javafx.animation.Timeline;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
 import javafx.scene.Scene;
 import javafx.util.Duration;
 public class ClockAnimation extends Application {
   @Override
   public void start(Stage primaryStage) {
     ClockPane clock = new ClockPane(); // Create a clock
     // Create a handler for animation
     EventHandler<ActionEvent> eventHandler = e -> {
       clock.setCurrentTime(); // Set a new clock time
     };
     // Create an animation for a running clock
     Timeline animation = new Timeline(
       new KeyFrame(Duration.millis(1000), eventHandler));
     animation.setCycleCount(Timeline.INDEFINITE);
     animation.play(); // Start animation
     Scene scene = new Scene(clock, 250, 250);
     primaryStage.setTitle("ClockAnimation");
     primaryStage.setScene(scene);
     primaryStage.show();
   }
   public static void main(String[] args) {
     launch(args);
   }
95
 }
                               (c) Paul Fodor and Pearson Inc.
   // ClockPane:
   import java.util.Calendar;
   import java.util.GregorianCalendar;
   import javafx.scene.layout.Pane;
   import javafx.scene.paint.Color;
   import javafx.scene.shape.Circle;
   import javafx.scene.shape.Line;
   import javafx.scene.text.Text;
   public class ClockPane extends Pane {
       private int hour;
       private int minute;
       private int second;
       // Clock pane's width and height
       private double w = 250, h = 250;
       public ClockPane() {
           setCurrentTime();
       }
       public ClockPane(int hour, int minute, int second) {
           this.hour = hour;
           this.minute = minute;
           this.second = second;
           paintClock();
       }
       public int getHour() {
           return hour;
       }
       public void setHour(int hour) {
           this.hour = hour;
           paintClock();
96     }
                               (c) Paul Fodor and Pearson Inc.
   }
   public int getMinute() {
       return minute;
   }
   public void setMinute(int minute) {
       this.minute = minute;
       paintClock();
   }
   public int getSecond() {
       return second;
   }
   public void setSecond(int second) {
       this.second = second;
       paintClock();
   }
   public double getW() {
       return w;
   }
   public void setW(double w) {
       this.w = w;
       paintClock();
   }
   public double getH() {
       return h;
   }
   public void setH(double h) {
       this.h = h;
       paintClock();
   }
   public void setCurrentTime() {
       Calendar calendar = new GregorianCalendar();
       this.hour = calendar.get(Calendar.HOUR_OF_DAY);
       this.minute = calendar.get(Calendar.MINUTE);
       this.second = calendar.get(Calendar.SECOND);
       paintClock(); // Repaint the clock
97 }
                                   (c) Paul Fodor and Pearson Inc.
      private void paintClock() {
          // Initialize clock parameters
          double clockRadius = Math.min(w, h) * 0.8 * 0.5;
          double centerX = w / 2;
          double centerY = h / 2;
          // Draw circle
          Circle circle = new Circle(centerX, centerY, clockRadius);
          circle.setFill(Color.WHITE);
          circle.setStroke(Color.BLACK);
          Text t1 = new Text(centerX - 5, centerY - clockRadius + 12, "12");
          Text t2 = new Text(centerX - clockRadius + 3, centerY + 5, "9");
          Text t3 = new Text(centerX + clockRadius - 10, centerY + 3, "3");
          Text t4 = new Text(centerX - 3, centerY + clockRadius - 3, "6");
          // Draw second hand
          double sLength = clockRadius * 0.8;
          double secondX = centerX + sLength * Math.sin(second * (2 * Math.PI       / 60));
          double secondY = centerY - sLength * Math.cos(second * (2 * Math.PI       / 60));
          Line sLine = new Line(centerX, centerY, secondX, secondY);
          sLine.setStroke(Color.RED);
          // Draw minute hand
          double mLength = clockRadius * 0.65;
          double xMinute = centerX + mLength * Math.sin(minute * (2 * Math.PI       / 60));
          double minuteY = centerY - mLength * Math.cos(minute * (2 * Math.PI       / 60));
          Line mLine = new Line(centerX, centerY, xMinute, minuteY);
          mLine.setStroke(Color.BLUE);
          // Draw hour hand
          double hLength = clockRadius * 0.5;
          double hourX = centerX + hLength * Math.sin((hour % 12 + minute / 60.0) * (2 * Math.PI / 12));
          double hourY = centerY - hLength * Math.cos((hour % 12 + minute / 60.0) * (2 * Math.PI / 12));
          Line hLine = new Line(centerX, centerY, hourX, hourY);
          hLine.setStroke(Color.GREEN);
          getChildren().clear();
          getChildren().addAll(circle, t1, t2, t3, t4, sLine, mLine, hLine);
      }
}98
                                        (c) Paul Fodor and Pearson Inc.
     Bouncing Ball
99
                 (c) Paul Fodor and Pearson Inc.
      import javafx.scene.layout.Pane;
      import javafx.animation.KeyFrame;
      import javafx.animation.Timeline;
      import javafx.beans.property.DoubleProperty;
      import javafx.scene.paint.Color;
      import javafx.scene.shape.Circle;
      import javafx.util.Duration;
      public class BallPane extends Pane {
          public final double radius = 20;
          private double x = radius, y = radius;
          private double dx = 1, dy = 1;
          private Circle circle = new Circle(x, y, radius);
          private Timeline animation;
          public BallPane() {
              circle.setFill(Color.GREEN); // Set ball color
              getChildren().add(circle); // Place a ball into this pane
              // Create an animation for moving the ball
              animation = new Timeline(new KeyFrame(Duration.millis(50), e -> moveBall()));
              animation.setCycleCount(Timeline.INDEFINITE);
              animation.play(); // Start animation
          }
          public void play() {
              animation.play();
          }
          public void pause() {
              animation.pause();
          }
          public void increaseSpeed() {
              animation.setRate(animation.getRate() + 0.1);
          }
          public void decreaseSpeed() {
              animation.setRate(
                      animation.getRate() > 0 ? animation.getRate() - 0.1 : 0);
          }
100
                                      (c) Paul Fodor and Pearson Inc.
          public DoubleProperty rateProperty() {
              return animation.rateProperty();
          }
101
                                        (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
public class BounceBallControl extends Application {
    @Override
    public void start(Stage primaryStage) {
        BallPane ballPane = new BallPane(); // Create a ball pane
        // Pause and resume animation
        ballPane.setOnMousePressed(e -> ballPane.pause());
        ballPane.setOnMouseReleased(e -> ballPane.play());
        // Increase and decrease animation
        ballPane.setOnKeyPressed(e -> {
            if (e.getCode() == KeyCode.UP) {
                ballPane.increaseSpeed();
            } else if (e.getCode() == KeyCode.DOWN) {
                ballPane.decreaseSpeed();
            }
        });
        Scene scene = new Scene(ballPane, 250, 150);
        primaryStage.setTitle("BounceBallControl");
        primaryStage.setScene(scene);
        primaryStage.show();
        // Must request focus after the primary stage is displayed
        ballPane.requestFocus();
    }
102
                                      (c) Paul Fodor and Pearson Inc.
      JavaFX support for mobile devices
        JavaFX has event programming support for mobile devices:
       javafx.scene.input.SwipeEvent,
       javafx.scene.input.TouchEvent,
       javafx.scene.input.ZoomEvent.
        Example:
       http://docs.oracle.com/javase/8/javafx/ev
       ents-tutorial/gestureeventsjava.htm
       http://docs.oracle.com/javase/8/javafx/ev
       ents-tutorial/toucheventsjava.htm
103
                           (c) Paul Fodor and Pearson Inc.
      Control Nodes
   Input control nodes:
104
                           (c) Paul Fodor and Pearson Inc.
       Labeled class
   A label is a display area for a short text, a node, or both
       It is often used to label other controls (usually text fields)
       Labels and buttons share many common properties: these common
        properties are defined in the Labeled class
105
                                 (c) Paul Fodor and Pearson Inc.
      Label class
106
             (c) Paul Fodor and Pearson Inc.
import   javafx.application.Application;
import   javafx.stage.Stage;
import   javafx.scene.Scene;
import   javafx.scene.control.ContentDisplay;
import   javafx.scene.control.Label;
import   javafx.scene.image.Image;
import   javafx.scene.image.ImageView;
import   javafx.scene.layout.HBox;
import   javafx.scene.layout.StackPane;
import   javafx.scene.paint.Color;
import   javafx.scene.shape.Circle;
import   javafx.scene.shape.Rectangle;
import   javafx.scene.shape.Ellipse;
public class LabelWithGraphic extends Application {
    @Override
    public void start(Stage primaryStage) {
        ImageView us = new ImageView(new Image("us.jpg"));
        Label lb1 = new Label("US\n50 States", us);
        lb1.setStyle("-fx-border-color: green; -fx-border-width: 2");
        lb1.setContentDisplay(ContentDisplay.BOTTOM);
        lb1.setTextFill(Color.RED);
        Label lb2 = new Label("Circle", new Circle(50, 50, 25));
        lb2.setContentDisplay(ContentDisplay.TOP);
        lb2.setTextFill(Color.ORANGE);
        Label lb3 = new Label("Retangle", new Rectangle(10, 10, 50, 25));
        lb3.setContentDisplay(ContentDisplay.RIGHT);
        Label lb4 = new Label("Ellipse", new Ellipse(50, 50, 50, 25));
        lb4.setContentDisplay(ContentDisplay.LEFT);
107
                                 (c) Paul Fodor and Pearson Inc.
      Ellipse ellipse = new Ellipse(50, 50, 50, 25);
      ellipse.setStroke(Color.GREEN);
      ellipse.setFill(Color.WHITE);
      StackPane stackPane = new StackPane();
      stackPane.getChildren().addAll(ellipse, new Label("JavaFX"));
      Label lb5 = new Label("A pane inside a label", stackPane);
      lb5.setContentDisplay(ContentDisplay.BOTTOM);
108
                          (c) Paul Fodor and Pearson Inc.
      ButtonBase and Button
  A button is a control that triggers an action event when clicked.
  JavaFX provides regular buttons, toggle buttons, check box buttons,
   and radio buttons.
  The common features of these buttons are defined in ButtonBase
   and Labeled classes.
109
                            (c) Paul Fodor and Pearson Inc.
import   javafx.application.Application;
import   javafx.stage.Stage;
import   javafx.geometry.Pos;
import   javafx.scene.Scene;
import   javafx.scene.control.Button;
import   javafx.scene.image.ImageView;
import   javafx.scene.layout.BorderPane;
import   javafx.scene.layout.HBox;
import   javafx.scene.layout.Pane;
import   javafx.scene.text.Text;
          return pane;
      }
111
                                 (c) Paul Fodor and Pearson Inc.
        CheckBox
   A CheckBox is used for the user to make a selection (square box).
   CheckBox inherits all the properties from ButtonBase and Labeled:
      onAction, text, graphic, alignment, graphicTextGap, textFill,
      contentDisplay.
112
                             (c) Paul Fodor and Pearson Inc.
import   javafx.event.ActionEvent;
import   javafx.event.EventHandler;
import   javafx.geometry.Insets;
import   javafx.scene.control.CheckBox;
import   javafx.scene.layout.BorderPane;
import   javafx.scene.layout.VBox;
import   javafx.scene.text.Font;
import   javafx.scene.text.FontPosture;
import   javafx.scene.text.FontWeight;
text.setFont(fontNormal);
          chkBold.setOnAction(handler);
          chkItalic.setOnAction(handler);
115
                                  (c) Paul Fodor and Pearson Inc.
import   static javafx.application.Application.launch;
import   javafx.geometry.Insets;
import   javafx.scene.control.RadioButton;
import   javafx.scene.control.ToggleGroup;
import   javafx.scene.layout.BorderPane;
import   javafx.scene.layout.VBox;
import   javafx.scene.paint.Color;
          rbRed.setOnAction(e -> {
              if (rbRed.isSelected()) {
                  text.setFill(Color.RED);
              }
116       });                     (c) Paul Fodor and Pearson Inc.
          rbGreen.setOnAction(e -> {
              if (rbGreen.isSelected()) {
                  text.setFill(Color.GREEN);
              }
          });
          rbBlue.setOnAction(e -> {
              if (rbBlue.isSelected()) {
                  text.setFill(Color.BLUE);
              }
          });
          return pane;
      }
117
                                 (c) Paul Fodor and Pearson Inc.
        TextField
  A text field can be used to enter or display a string. TextField is a
      subclass of TextInputControl.
118
                              (c) Paul Fodor and Pearson Inc.
import static javafx.application.Application.launch;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
public class TextFieldDemo extends RadioButtonDemo{
    @Override
    protected BorderPane getPane() {
        BorderPane pane = super.getPane();
          return pane;
      }
120
                            (c) Paul Fodor and Pearson Inc.
        ComboBox
   A combo box, also known as a choice list or drop-down list, contains
      a list of items from which the user can choose.
121
                              (c) Paul Fodor and Pearson Inc.
      ListView
       A list view is a component that performs basically the same
        function as a combo box, but it enables the user to choose a
        single value or multiple values.
122
                           (c) Paul Fodor and Pearson Inc.
import   javafx.application.Application;
import   javafx.stage.Stage;
import   javafx.scene.Scene;
import   javafx.scene.control.ListView;
import   javafx.scene.control.ScrollPane;
import   javafx.scene.control.SelectionMode;
import   javafx.scene.image.ImageView;
import   javafx.scene.layout.BorderPane;
import   javafx.scene.layout.FlowPane;
import   javafx.collections.FXCollections;
        lv.getSelectionModel().selectedItemProperty().addListener(
          ov -> {
            imagePane.getChildren().clear();
            for (Integer i: lv.getSelectionModel().getSelectedIndices()) {
              imagePane.getChildren().add(ImageViews[i]);
            }
        });
124
                                   (c) Paul Fodor and Pearson Inc.
        ScrollBar
   A scroll bar is a control that enables the user
      to select from a range of values. The
      scrollbar appears in two styles: horizontal
      and vertical.
125
                              (c) Paul Fodor and Pearson Inc.
         Slider
 Slider is similar to ScrollBar, but Slider
      has more properties and can appear in
      many forms.
126
                              (c) Paul Fodor and Pearson Inc.
      Media
   The Media class is used to obtain the source of a media type.
   The MediaPlayer class is used to play and control the media.
   The MediaView class is used to display video.
127
                           (c) Paul Fodor and Pearson Inc.
       MediaPlayer
   The MediaPlayer class plays and controls media with properties:
      autoPlay, currentCount, cycleCount, mute, volume, and
      totalDuration.
128
                           (c) Paul Fodor and Pearson Inc.
        MediaView
   The MediaView class is a subclass of Node that provides a view of the
      Media being played by a MediaPlayer.
       The MediaView class provides the properties for viewing the media.
129
                              (c) Paul Fodor and Pearson Inc.
       Example: Using Media
 This example displays a video in a view: use the play/pause button to
  play or pause the video and use the rewind button to restart the video,
  and use the slider to control the volume of the audio.
130
                            (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.geometry.Pos;
import javafx.util.Duration;
public class MediaDemo extends Application {
    private static final String MEDIA_URL = "sample.mp4";
    @Override
    public void start(Stage primaryStage) {
        Media media = new Media(MEDIA_URL);
        MediaPlayer mediaPlayer = new MediaPlayer(media);
        MediaView mediaView = new MediaView(mediaPlayer);
        Button playButton = new Button(">");
        playButton.setOnAction(e -> {
            if (playButton.getText().equals(">")) {
                mediaPlayer.play();
                playButton.setText("||");
            } else {
                mediaPlayer.pause();
                playButton.setText(">");
131         }                   (c) Paul Fodor and Pearson Inc.
        });
          Button rewindButton = new Button("<<");
          rewindButton.setOnAction(e -> mediaPlayer.seek(Duration.ZERO));
          Slider slVolume = new Slider();
          slVolume.setPrefWidth(150);
          slVolume.setMaxWidth(Region.USE_PREF_SIZE);
          slVolume.setMinWidth(30);
          slVolume.setValue(50);
          mediaPlayer.volumeProperty().bind(slVolume.valueProperty().divide(100));
          HBox hBox = new HBox(10);
          hBox.setAlignment(Pos.CENTER);
          hBox.getChildren().addAll(playButton, rewindButton,
                  new Label("Volume"), slVolume);
          BorderPane pane = new BorderPane();
          pane.setCenter(mediaView);
          pane.setBottom(hBox);
132
                                 (c) Paul Fodor and Pearson Inc.
         CSS
  Cascading Style Sheets (CSS) is a language used for describing the look and
      formatting of a document.
       CSS is designed primarily to enable the separation of document content
        from document presentation (layout, colors, and fonts).
         It is used to style web pages and user interfaces written in HTML, XHTML, and any
          kind of XML document.
       The CSS language specifications are Web standards maintained by
        theWorld Wide Web Consortium (W3C).
       CSS rule set example:
133
                                   (c) Paul Fodor and Pearson Inc.
       JavaFX CSS
   JavaFX Cascading Style Sheets (CSS) is based on the W3C CSS and
      allows to customize and develop themes for JavaFX controls and
      scene graph objects
       http://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html
       JavaFX uses the prefix "-fx-" to define its vendor CSS properties
        (separate from W3C CSS).
   A style sheet uses the style class or style id to define styles.
       Mutiple style classes can be applied to a single node and a style id to a
        unique node.
       The syntax .styleclass defines a style class.
       The syntax #styleid defines a style id.
134
                                 (c) Paul Fodor and Pearson Inc.
      Style Class and Style ID
   mystyle.css:
      .plaincircle {
        -fx-fill: white;
        -fx-stroke: black;
      }
      .circleborder {
        -fx-stroke-width: 5;
        -fx-stroke-dash-array: 12 2 4 2;
      }
      .border {
        -fx-border-color: black;
        -fx-border-width: 5;
      }
      #redcircle {
        -fx-fill: red;
        -fx-stroke: red;
      }
      #greencircle {
        -fx-fill: green;
        -fx-stroke: green;
      }
135
                          (c) Paul Fodor and Pearson Inc.
  import javafx.application.Application;
  import javafx.stage.Stage;
  import javafx.scene.Scene;
  import javafx.scene.layout.HBox;
  import javafx.scene.layout.Pane;
  import javafx.scene.shape.Circle;
  public class StyleSheetDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
      HBox hBox = new HBox(5);
      Scene scene = new Scene(hBox, 300, 250);
      // Load the stylesheet
      scene.getStylesheets().add("mystyle.css");
      Pane pane1 = new Pane();
      Circle circle1 = new Circle(50, 50, 30);
      Circle circle2 = new Circle(150, 50, 30);
      Circle circle3 = new Circle(100, 100, 30);
      pane1.getChildren().addAll(circle1, circle2, circle3);
      pane1.getStyleClass().add("border");
      circle1.getStyleClass().add("plaincircle"); // Add a style class
      circle2.getStyleClass().add("plaincircle"); // Add a style class
      circle3.setId("redcircle"); // Add a style id
      Pane pane2 = new Pane();
      Circle circle4 = new Circle(100, 100, 30);
136
                           (c) Paul Fodor and Pearson Inc.
          circle4.getStyleClass().addAll("circleborder", "plainCircle");
          circle4.setId("greencircle"); // Add a style class
          pane2.getChildren().add(circle4);
          pane2.getStyleClass().add("border");
hBox.getChildren().addAll(pane1, pane2);
          primaryStage.setTitle("StyleSheetDemo");
          primaryStage.setScene(scene);
          primaryStage.show();
      }
137
                               (c) Paul Fodor and Pearson Inc.
      QuadCurve
       A quadratic curve is mathematically defined as a quadratic
        polynomial.
      QuadCurve(double startX, double startY,
      double controlX, double controlY, double
      endX, double endY)
(controlX, controlY)
                                                      (endX, endY)
                      (startX, startY)
138
                                   (c) Paul Fodor and Pearson Inc.
          QuadCurve
                                     The getter and setter methods for property values and a getter for property
      javafx.scene.shape.QuadCurve   itself are provided in the class, but omitted in the UML diagram for brevity.
139
                                       (c) Paul Fodor and Pearson Inc.
        Menus
       Menus make selection easier and are widely used in window
        applications.
         JavaFX provides five classes that implement menus: MenuBar,
          Menu, MenuItem, CheckMenuItem, and
          RadioButtonMenuItem.
       MenuBar is a top-level menu component used to hold the
        menus.
         A menu consists of menu items that the user can select (or
          toggle on or off).
         A menu item can be an instance of MenuItem,
          CheckMenuItem, or RadioButtonMenuItem.
         Menu items can be associated with nodes and keyboard
140       accelerators.    (c) Paul Fodor and Pearson Inc.
   import   javafx.application.Application;
   import   javafx.stage.Stage;
   import   javafx.scene.Scene;
   import   javafx.scene.control.Button;
   import   javafx.scene.control.Label;
   import   javafx.scene.control.Menu;
   import   javafx.scene.control.MenuBar;
   import   javafx.scene.control.MenuItem;
   import   javafx.scene.control.TextField;
   import   javafx.scene.input.KeyCombination;
   import   javafx.scene.layout.HBox;
   import   javafx.scene.layout.VBox;
   import   javafx.geometry.Pos;
         menuItemAdd.setAccelerator(
           KeyCombination.keyCombination("Ctrl+A"));
         menuItemSubtract.setAccelerator(
           KeyCombination.keyCombination("Ctrl+S"));
         menuItemMultiply.setAccelerator(
           KeyCombination.keyCombination("Ctrl+M"));
         menuItemDivide.setAccelerator(
           KeyCombination.keyCombination("Ctrl+D"));
         HBox hBox1 = new HBox(5);
         tfNumber1.setPrefColumnCount(2);
         tfNumber2.setPrefColumnCount(2);
142      tfResult.setPrefColumnCount(2);
                                 (c) Paul Fodor and Pearson Inc.
          hBox1.getChildren().addAll(new Label("Number 1:"), tfNumber1,
            new Label("Number 2:"), tfNumber2, new Label("Result:"),
            tfResult);
          hBox1.setAlignment(Pos.CENTER);
            double   result = 0;
            switch   (operator) {
              case   '+': result =   number1    +   number2;        break;
              case   '-': result =   number1    -   number2;        break;
              case   '*': result =   number1    *   number2;        break;
              case   '/': result =   number1    /   number2;        break;
            }
            tfResult.setText(result + "");
          };
144
                                        (c) Paul Fodor and Pearson Inc.
      Context Menu
       A context menu (also known as a popup menu) is like a
        regular menu, but does not have a menu bar and can float
        anywhere on the screen.
         Creating a context menu is similar to creating a regular menu.
           First, create an instance of ContextMenu, then add MenuItem,
            CheckMenuItem, and RadioMenuItem to the context menu.
145
                            (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.image.ImageView;
public class ContextMenuDemo extends Application {
  @Override
  public void start(Stage primaryStage) {
    ContextMenu contextMenu = new ContextMenu();
    MenuItem menuItemNew = new MenuItem("New",
      new ImageView("image/new.gif"));
    MenuItem menuItemOpen = new MenuItem("Open",
      new ImageView("image/open.gif"));
    MenuItem menuItemPrint = new MenuItem("Print",
      new ImageView("image/print.gif"));
    MenuItem menuItemExit = new MenuItem("Exit");
    contextMenu.getItems().addAll(menuItemNew, menuItemOpen,
      menuItemPrint, menuItemExit);
    Pane pane = new Pane();
    Scene scene = new Scene(pane, 300, 250);
    primaryStage.setTitle("ContextMenuDemo");
    primaryStage.setScene(scene);
    primaryStage.show();
146
                           (c) Paul Fodor and Pearson Inc.
        pane.setOnMousePressed(
          e -> contextMenu.show(pane, e.getScreenX(), e.getScreenY()));
147
                               (c) Paul Fodor and Pearson Inc.
      SplitPane
       The SplitPane class can be used to display multiple panes and
        allow the user to adjust the size of the panes.
148
                            (c) Paul Fodor and Pearson Inc.
      TabPane
       The TabPane class can be used to display multiple panes with
        tabs.
149
                           (c) Paul Fodor and Pearson Inc.
      TabPane
             javafx.scene.control.Control                     The getter and setter methods for property values and
                                                              a getter for property itself are provided in the class, but
                                                              omitted in the UML diagram for brevity.
             javafx.scene.control.TabPane
      -side: ObjectProperty<Side>                    The position of the tab in the tab pane. Possible values are:
                                                     Side.TOP, Side.BOTTOM, Side.LEFT, and Side.RIGHT (default:
                                                     Side.TOP).
                                                     Creates a default tab pane.
      +TabPane()
      +getTabs(): ObservableList<Tab>                Returns a list of tabs in this tab pane.
                           java.lang.Object                       The getter and setter methods for property values and
                                                                  a getter for property itself are provided in the class, but
                                                                  omitted in the UML diagram for brevity.
                       javafx.scene.control.Tab
                      javafx.scene.control.Control             The getter and setter methods for property values and
                                                               a getter for property itself are provided in the class, but
                                                               omitted in the UML diagram for brevity.
                javafx.scene.control.TableView<S>
        CellDataFeatures<S,T>,ObservableValue
        <T>>>
      -graphic: ObjectProperty<Node>              The graphic for this TableColumn.
      -id: StringProperty                         The id for this TableColumn.
      -resizable: BooleanProperty                 Indicates whether the column is resizable.
      -sortable: BooleanProperty                  Indicates whether the column is sortable.
      -text: StringProperty                       Text in the table column header.
      -style: StringProperty                      Specify the CSS style for the column.
      -visible: BooleanProperty                   Specify whether the column is visible (default: true).
      +TableColumn()                              Creates a default TableColumn.
      +TableColumn(text: String)                  Creates a TableView with the specified header text.
152
                                            (c) Paul Fodor and Pearson Inc.
        FXML
       FXML is a declarative XML-based language created by
       Oracle Corporation for defining the user interface of a
       JavaFX 2.0 application.
        It can be edited and created using the JavaFX Scene
         Builder 2 (downloaded separately from J2SE)
        Create a new JavaFX project in Netbeans and you
         will get 3 files: an FXML file with the UI design, a
         main application .java file that loads the FXML and a
         controller for the event handlers for the UI Nodes.
153
                         (c) Paul Fodor and Pearson Inc.
FXML document:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="200"
xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8"
fx:controller="javafxapplication1.FXMLDocumentController">
      <children>
       <FlowPane prefHeight="200.0" prefWidth="200.0">
           <children>
                   <Label fx:id="label" minHeight="16" minWidth="69"
                           text="Welcome to FXML" />
           </children>
       </FlowPane>
      </children>
</AnchorPane>
154
                                (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
public class JavaFXApplication5 extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
public class FXMLDocumentController implements Initializable {
    @FXML
    private Label label;
    @Override
    public void initialize(URL url, ResourceBundle rb) {
    }
155
}
                               (c) Paul Fodor and Pearson Inc.
      HTML in JavaFX
       HTML intro.: the Internet Web pages format
       Example: html_sample_01.html
        <!DOCTYPE html>
        <html>                         ← This is the HTML tag. Every HTML page has one
        <body>
                                                            ← This is a paragraph
        <p>My first paragraph.</p>
        </body>
        </html>
156
                          (c) Paul Fodor and Pearson Inc.
      HTML
       HTML is a language for describing web pages.
       HTML stands for Hyper Text Markup Language
       HTML is a markup language
       A markup language is a set of markup tags
       The tags describe document content
       HTML documents contain HTML tags and plain text
       HTML documents are also called web pages
157
                         (c) Paul Fodor and Pearson Inc.
      HTML
       HTML markup tags are usually called HTML tags
       HTML tags are keywords (tag names) surrounded by angle
          brackets like <html>
         HTML tags normally come in pairs like <b> and </b>
         The first tag in a pair is the start tag, the second tag is
          the end tag
         The end tag is written like the start tag, with a forward
          slash before the tag name
         Start and end tags are also called opening tags and closing
          tags
                <tagname>content</tagname>
158                     <p>This is a paragraph.</p>
                            (c) Paul Fodor and Pearson Inc.
      HTML by Examples
       http://www.w3schools.com/html/html_examples.asp
       HTML links:
         <a href="http://www.w3schools.com">This is a link</a>
         It appears as: This is a link
       HTML images:
         <img src="w3schools.jpg" width="104" height="142">
         It appears as:
159
                              (c) Paul Fodor and Pearson Inc.
          JavaFX with HTML
 You can put HTML code in JavaFX:
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.control.Button;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
public class HTMLDemo extends Application {
  @Override
  public void start(Stage primaryStage) {
     WebView browser = new WebView();
     WebEngine webEngine = browser.getEngine();
     webEngine.loadContent("<html><b><u>T</u>wo</b><br>lines</html>");
     StackPane root = new StackPane();
     root.getChildren().add(browser);
     Scene scene = new Scene(root, 100, 150); import org.w3c.dom.Document;
     primaryStage.setTitle("Hello World!");                // ... get the document of the engine
     primaryStage.setScene(scene);                         Document doc = webEngine.getDocument();
     primaryStage.show();                                  // and the elements
                                                           import org.w3c.dom.Element;
  }
                                                           ... Element el = doc.getElementById("id1");
  public static void main(String[] args) {
     launch(args);
  }
 160
}                                  (c) Paul Fodor and Pearson Inc.
        JavaFX with HTML
 You can get the Document only when the asynchronized WebEngine had
  finished loading the page. That is,
  Document doc = webEngine.getDocument();
  may be null if the page is not loaded yet.
   Solution: listen to the state of the WebEngine object to know when it is done loading:
      engine.getLoadWorker().stateProperty().addListener(
        (ObservableValue<? extends State> observable,
              State oldValue, State newValue)
              -> {
              if (newValue == State.SUCCEEDED)
              docManager.setStatsDoc(engine.getDocument());
      });
161
                                  (c) Paul Fodor and Pearson Inc.
         javafx.scene.canvas.Canvas
       javafx.scene.canvas.Canvas is an image that can be drawn on using a
        set of graphics commands provided by a GraphicsContext.
       javafx.scene.canvas.GraphicsContext issues draw calls to
        a Canvas using a buffer:
         each call pushes the necessary parameters onto the buffer where they
         will be later rendered onto the image of the Canvas node by the
         rendering thread at the end of a pulse.
        Canvas canvas = new Canvas(250,250);
        GraphicsContext gc =
            canvas.getGraphicsContext2D();
        gc.fillRect(75,75,100,100);
162
                               (c) Paul Fodor and Pearson Inc.
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.stage.Screen;
import java.util.ArrayList;
import java.util.Iterator;
public class CanvasDemo extends Application {
    Stage primaryStage;
    Scene scene;
    Canvas canvas;
    GraphicsContext gc;
    Image logo1Image, logo2Image;
    ArrayList<Point2D> logo1Locations, logo2Locations;
    @Override
    public void start(Stage initPrimaryStage) {
        primaryStage = initPrimaryStage;
        initStage();
        initData();
        initGUI();
163     initHandlers();
                            (c) Paul Fodor and Pearson Inc.
    }
      public void initStage() {
          Screen screen = Screen.getPrimary();
          Rectangle2D bounds = screen.getVisualBounds();
          primaryStage.setX(bounds.getMinX());
          primaryStage.setY(bounds.getMinY());
          primaryStage.setWidth(bounds.getWidth());
          primaryStage.setHeight(bounds.getHeight());
      }
      public void initData() {
          logo1Locations = new ArrayList();
          logo2Locations = new ArrayList();
          logo1Image = new Image("file:images/logo1.png");
          logo2Image = new Image("file:images/logo2.png");
      }
      public void initGUI() {
          canvas = new Canvas();
          gc = canvas.getGraphicsContext2D(); // is graphics destination: monitor
          Group root = new Group();
          root.getChildren().add(canvas);
          scene = new Scene(root);
          primaryStage.setScene(scene);
          primaryStage.show();
          canvas.setWidth(scene.getWidth());
          canvas.setHeight(scene.getHeight());
      }
164
                                (c) Paul Fodor and Pearson Inc.
 public void initHandlers() {
        canvas.setOnMouseClicked(mouseEvent -> {
            Point2D point = new Point2D(mouseEvent.getX(), mouseEvent.getY());
            if (!logo1Locations.contains(point)) {
                logo1Locations.add(point);
            }
            draw();
        });
        canvas.setOnMouseDragged(mouseEvent -> {
            Point2D point = new Point2D(mouseEvent.getX(), mouseEvent.getY());
            if (!logo2Locations.contains(point)) {
                logo2Locations.add(point);
            }
            draw();
        });
    }
    public void draw() {
        Iterator<Point2D> it = logo1Locations.iterator();
        while (it.hasNext()) {
            Point2D p = it.next();
            gc.drawImage(logo1Image, p.getX(), p.getY());
        }
        it = logo2Locations.iterator();
        while (it.hasNext()) {
            Point2D p = it.next();
            gc.drawImage(logo2Image, p.getX(), p.getY());
        }
    }
    public static void main(String[] args) {
165     launch();
                                (c) Paul Fodor and Pearson Inc.
    }}
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.geometry.Rectangle2D;
import javafx.scene.Group;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
import javafx.stage.Screen;
import java.util.ArrayList;
public class PentaApp extends Application {
    private Stage primaryStage;
    private Scene scene;
    private Canvas canvas;
    private GraphicsContext gc;
    private ArrayList<double[]> xPoints;
    private ArrayList<double[]> yPoints;
    private ArrayList<Color> colors;
    @Override
    public void start(Stage initPrimaryStage) {
        primaryStage = initPrimaryStage;
        initStage();
        initData();
        initGUI();
166     initHandlers();
                            (c) Paul Fodor and Pearson Inc.
    }
    public void initStage() {
        primaryStage.setTitle("Penta App");
        Screen screen = Screen.getPrimary(); // is graphics destination: monitor
        Rectangle2D bounds = screen.getVisualBounds();
        primaryStage.setX(bounds.getMinX());
        primaryStage.setY(bounds.getMinY());
        primaryStage.setWidth(bounds.getWidth());
        primaryStage.setHeight(bounds.getHeight());
    }
    public void initData() {
        xPoints = new ArrayList();
        yPoints = new ArrayList();
        colors = new ArrayList();
    }
    public void initGUI() {
        canvas = new Canvas();
        gc = canvas.getGraphicsContext2D();
        Group root = new Group();
        root.getChildren().add(canvas);
        scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
        canvas.setWidth(scene.getWidth());
        canvas.setHeight(scene.getHeight());
    }
     public void initHandlers() {
        canvas.setOnMouseClicked(mouseEvent -> {
            if (mouseEvent.getClickCount() == 2) {
                xPoints.clear();
167             yPoints.clear();
                               (c) Paul Fodor and Pearson Inc.
                  colors.clear();
                  gc.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
              }
          });
          canvas.setOnMouseDragged(mouseEvent -> {
              double x = mouseEvent.getX();
              double y = mouseEvent.getY();
              double[] xs = new double[5];
              double[] ys = new double[5];
              // CENTER
              xs[0] = x;
              ys[0] = y - (int) (Math.random() * 20)            - 1;
              // TOP-RIGHT POINT
              xs[1] = x + (int) (Math.random() * 15)            + 1;
              ys[1] = y - (int) (Math.random() * 10)            - 1;
              // BOTTOM-RIGHT POINT
              xs[2] = x + (int) (Math.random() * 10)            + 1;
              ys[2] = y + (int) (Math.random() * 15)            + 1;
              // BOTTOM-LEFT POINT
              xs[3] = x - (int) (Math.random() * 10)            - 1;
              ys[3] = y + (int) (Math.random() * 15)            + 1;
              // TOP-LEFT POINT
              xs[4] = x - (int) (Math.random() * 15)            - 1;
              ys[4] = y - (int) (Math.random() * 10)            - 1;
              xPoints.add(xs);
              yPoints.add(ys);
              int r = (int) (Math.random() * 256);
              int g = (int) (Math.random() * 256);
              int b = (int) (Math.random() * 256);
              colors.add(Color.rgb(r, g, b));
              PentaApp.this.draw();
168       });
      }                             (c) Paul Fodor and Pearson Inc.
      public void draw() {
          for (int i = 0; i < xPoints.size(); i++) {
              double[] xVertices = xPoints.get(i);
              double[] yVertices = yPoints.get(i);
              for (int j = 0; j < 5; j++) {
                  xVertices[j] += (int) (Math.random() * 9) - 4;
                  yVertices[j] += (int) (Math.random() * 9) - 4;
              }
              Color color = colors.get(i);
              gc.setFill(color);
              gc.fillPolygon(xVertices, yVertices, 5);
              gc.setStroke(Color.BLACK);
              gc.strokePolygon(xVertices, yVertices, 5);
          }
      }
169
                          (c) Paul Fodor and Pearson Inc.