Java FX
Java FX
Introduction
§14.1 Introduction
Graphical User Interface (GUI) applications, as
opposed to console UI applications, rely heavily
on objects
JavaFX is a framework and (large) set of objects
we can use to develop GUI-based applications
The JavaFX API is a good example of how
object-oriented principles can be applied in
software development
§14.1 Introduction
This chapter introduces us to creating the UI, but
it will be very simple, and it
won’t actually do anything
(like the façade of a building
in a movie set; it doesn’t
have anything “behind it”)
Chapter 15 (Event-Driven Programming) shows
us how to get that interface to do things (how to
link executable code to the UI elements)
Chapter 16 shows us more elements we can use
to add different kinds of functionality to the UI
Section 14.2
JavaFX vs Swing vs
AWT
§14.2: JavaFX vs Swing vs AWT
Java was first released with GUI support in
something called the Abstract Windows Toolkit
(AWT)
AWT wasn’t bad, but it had some limitations, and
some particular problems with how it was
implemented on some platforms
Ultimately, AWT (which still exists, but isn’t used
much anymore) was replaced by a new library
called Swing, which was more versatile, more
robust, and more flexible.
§14.2: JavaFX vs Swing vs AWT
Swing was designed primarily for use in desktop
applications (although you could do some web-
based things with it, too).
Swing has now been replaced by a completely
new GUI library called JavaFX
You can still use Swing (for the foreseeable
future), but Oracle isn’t going to develop it any
further – it’s essentially a dead-end technology
Java has replaced Swing with JavaFX
How long until JavaFX is replaced by something
else? Nobody knows; probably many years
§14.2: JavaFX vs Swing vs AWT
JavaFX lets us write RIAs (Rich Internet
Applications), which essentially run under a
browser (IE / FireFox / Chrome / Safari) just like
they run on a desktop
Previously, the cross-platform (desktop vs
browser) experience was delivered by Java
Applets, but applets are pretty much dead, too.
If you need to learn Swing, see Liang’s 9e, and I
will provide lecture slides; otherwise, just learn
JavaFX, and don’t look back.
Section 14.3
The Basic
Structure of a
JavaFX Program
§14.3: JavaFX Programs: Basic
Structure
In Chapter 13, we said that abstract classes
were used to create a starting point for
inheritance, but that the abstract class is never
intended to be instantiated itself – it’s too
incomplete.
JavaFX programs all start not as some “regular”
class like we’ve been doing, but as an extension
of the abstract Application class in JavaFX,
javafx.application.Application
(next slide)
§14.3: JavaFX Programs: Basic
Structure
public class MyProgram
{
// Body of class
}
Becomes:
import javafx.application.Application;
…
public class MyProgram extends Application
{
// Body of class
}
§14.3: Running JavaFX Apps in
Eclipse
There is a problem with the default installation of
Eclipse and getting JavaFX to run. Here’s the
fix:
When you create a JavaFX project, right-click on
the project (under the Package Explorer in
Eclipse), and select “Properties”
In the window that
appears, click on
“Java Build Path”
on the left side, then
“Add External JARs”
on the right
§14.3: Running JavaFX Apps in
Eclipse
Navigate to:
C:\Program Files (x86)\Java\jre1.8.0_40\lib\ext\
Double-click on jfxrt.jar, which should now
appear at the top of your build path
Click on the “Order and Export” tab
§14.3: Running JavaFX Apps in
Eclipse
Click on jfxrt.jar to highlight it
Then click the button labeled “Top” to move it to
the top of the list
Click “OK”
§14.3: Our First JavaFX Program
Our first JavaFX program will open a window, whose
title bar will display “MyJavaFX”, and which will have
a (huge) button in the middle labeled “OK”
First, the result, and then the code:
§14.3: Our First JavaFX Program
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
/**
* 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)
{
Application.launch(args);
}
}
§14.3: Our First JavaFX Program
JavaFX programs are based on the analogy of a
stage (think “theater stage” for the moment).
On the stage are scenes, and each scene is also
made up of other components.
On a theater stage, the stage may be divided into
portions, where individual scenes take place.
Each scene’s set will have actors, props, backdrops,
lighting, etc.
In JavaFX, we create the components, add them to
scenes, and then add scenes to the stage
§14.3: Our First JavaFX Program
In JavaFX, the stage is the window our code runs in
Since every GUI application, by definition, involves a
window with the UI, we get the primaryStage by
default when the application launches.
Our applications are not limited to a single stage
Just as a music festival may have simultaneous
performances on multiple stages, we can have more
than one stage (window) in our programs.
The code to set
up this two-
stage UI is on
the next slide
§14.3: Our First JavaFX Program
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
public class MultipleStageDemo extends Application
{
@Override // Override the start method in the Application class
public void start(Stage primaryStage)
{
// Create a scene and place a button in the scene
Scene scene = new Scene(new Button("OK"), 200, 250);
primaryStage.setTitle("MyJavaFX"); // Set the stage title
primaryStage.setScene(scene); // Put the scene in the stage
primaryStage.show(); // Display the stage
Panes, UI Controls,
and Shapes
§14.4: Panes, UI Controls, and
Shapes
In Listing 14.1, we put the button directly on the
scene, which centered the button and made it
occupy the entire window.
Rarely is this what we really want to do
One approach is to specify the size and location
of each UI element (like the buttons)
A better solution is to
put the UI elements
(known as nodes)
into containers called
panes, and then add
the panes to the scene.
§14.4: Panes, UI Controls, and
Shapes
Panes can even contain other panes:
§14.4: Panes, UI Controls, and
Shapes
The following slide shows the
code to create this version of
the same UI, with a single
button inside a pane (so that
the button doesn’t occupy the whole stage).
It uses a StackPane (which we’ll discuss later).
In order to add something to a pane, we need to
access the list of things IN the pane, much like an
ArrayList.
The new item we’ll add will be a new child of the
pane, so we’re adding it to the list of the pane’s
children
§14.4: Panes, UI Controls, and
import
Shapes
javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.scene.layout.StackPane;
// Create a 200-x-200 scene from the pane, and place the scene in the stage
Scene scene = new Scene(pane, 200, 200);
primaryStage.setTitle("ShowCircle"); // Set the stage title
primaryStage.setScene(scene); // Place the scene in the stage
primaryStage.show(); // Display the stage
}
}
Section 14.5
Property Binding
§14.5 Property Binding
In the previous example, the (x, y) location of the
center of the circle was static – it will always be
located at (100, 100).
What if we want it to be centered in the pane,
such that if we re-size the window, the circle will
move to stay centered?
In order to do so, the circle’s center has to be
bound to the pane’s height and width, such that a
change to the height or width will force a change
to the x or y value of the circle’s center.
This is what property binding is all about
§14.5 Property Binding
Like most things Java-esque, we get more new
terminology
The target object (called the binding object) gets
bound to the source object (the bindable object)
When there’s a change to the source, it gets
automatically sent to the target.
The following listing (14.5) shows how to bind the
circle’s X and Y center values to the pane’s width
(for clarity, the import statements at the top
have been omitted)
§14.5 Property Binding
public class ShowCircleCentered extends Application
{
@Override // Override the start method in the Application class
public void start(Stage primaryStage)
{
// Create a pane to hold the circle
Pane pane = new Pane();
d2.setValue(70.2);
Common
Properties and
Methods for
§14.6 Common Node Properties &
Methods
Nodes share many common properties
This section introduces two – style and rotate
JavaFX style properties are a lot like CSS
(Cascading Style Sheets) use to specify styles in
HTML (Web) pages.
For more on HTML and CSS, see Liang supplements
V.A and V.B (on the text’s companion website)
Thus, it’s known as JavaFX CSS
The official Java documentation on these
properties can be found here
§14.6 Common Node Properties &
Methods
In Matlab, we could set both the color and style
of a line at once
Similarly, in JavaFX CSS, we can set more than
one property at a time
Each property begins with the prefix –fx–, and
is of the form styleName:value, with multiple
settings separated by semicolons.
For example:
circle.setStyle(“-fx-stroke: black; -fx-fill: red;”);
Is equivalent to:
circle.setStroke(Color.BLACK);
circle.setFill(Color.RED);
§14.6 Common Node Properties &
Methods
Listing 14.7 (pp. 545 – 546) and next slide shows
a program that creates a button with a blue
border, uses JavaFX CSS to set its pane’s style
to a red border and a light gray fill, and then
rotates the button 45 degrees
Note: positive rotation is clockwise;
negative is CCW
§14.6 Common Node Properties &
Methods
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;
import javafx.scene.layout.StackPane;
pane.setRotate(45); // rotate pane and set its style before adding to scene
pane.setStyle("-fx-border-color: red; -fx-background-color: lightgray;");
Notes:
setRotate is a method in the Node class, so all nodes can
be rotated.
If you use the URL-based constructor for Image, it must
include “http://”
Java assumes the image is located in the same directory
as the .class file. If it’s located elsewhere, you must use
either a full path or a relative path to specify where
Section 14.10
Layout Panes
§14.10: Layout Panes
As we’ve said (and have been doing), we add
our Nodes to a Pane, and then add the Pane to a
Scene, and then the Scene to a Stage (probably
the primary stage).
How do we arrange (i.e., lay out) the Nodes on
the pane?
Java has several different kinds of Panes that do
a lot of the layout work for us.
This section examines these layout panes in
more detail
We’ve already used the Pane , HBox, and
StackPane; we’ll start with the FlowPane…
§14.10: Layout Panes
Name Description
Pane Base class for layout panes. Use its getChildren() method to
return the list of nodes on the pane (or add to that list)
Provides no particular layout capabilities – it’s a “blank canvas”
typically used to draw shapes on
StackPane Places nodes on top of each other in the center of the pane
FlowPane Places the notes row-by-row horizontally or column-by-column
vertically (reading order)
GridPane Provide a 2-D grid of cells, into which we can place nodes
BorderPane Divides pane into top, bottom, left, right, and center regions
HBox Places nodes in a single (horizontal) row
VBox Places nodes in a single (vertical) column
§14.10.1: The FlowPane
The FlowPane can be set up to work in “reading
order” (sequential rows left-to-right), by using
Orientation.HORIZONTAL or in sequential top-
to-bottom columns (Orientation.VERTICAL)
You can also specify the gap between nodes (in
pixels)
So far, we have seen putting Button and
ImageView nodes on a pane.
Listing 14.10 (p. 553 and next slide) uses the
FlowPane and Label & TextField nodes.
Let’s take a closer look…
§14.10.1: The FlowPane
public void start(Stage primaryStage) // From Listing 14.10 (p. 553)
{
// Create a pane and set its properties
FlowPane pane = new FlowPane();
pane.setPadding(new Insets(11, 12, 13, 14));
pane.setHgap(5);
pane.setVgap(5); Setting the padding with an Insets object gives us
a margin inside the pane. Just as angles are
always clockwise, the Insets are specified in
// Place nodes in the pane
clockwise
pane.getChildren().addAll(new order from the
Label("First top, so this pane will have
Name:"),
new TextField(), new Label("MI:"));
an 11-pixel gap between the top of the pane and
TextField tfMi = new TextField();
the first row, a 12-pixel gap between the right-most
tfMi.setPrefColumnCount(1);
node and the right side of the pane, 13 pixels at
pane.getChildren().addAll(tfMi,
the bottom,newand
Label("Last
14 pixels on Name:"),
the left side.
new TextField());
A few notes:
The “Add” button is right-aligned within its cell (l. 31)
The whole frame is centered (l. 17)
The labels get the default horizontal alignment of “left”
We specify the column first (backwards from arrays)
Not every cell needs to be filled
Elements can be moved from one cell to another
§14.10.3: The BorderPane
The BorderPane divides the
pane into five “regions”
The program in Listing 14.12
places a CustomPane in each
region.
The CustomPane is an extension of StackPane,
which is used to display the labels
Note that a Pane is also a Node, so a Pane can
contain another Pane
If a region is empty, it’s simply not shown
We can clear a region with set<region>(null)
§14.10.4: HBox and VBox
The FlowPane gave us rows and columns (in
reading order)
The HBox and VBox panes give us a single row
or column (respectively)
The program in Listing 14.13 (p. 559) illustrates
the use of a BorderPane, an HBox, and a VBox
It creates a BorderPane with only the Top and
Left regions used (the others are empty)
The Top region contains an HBox with two
buttons and an ImageView
The Left region contains a VBox with 5 labels
§14.10.4: HBox and VBox
The result:
Section 14.11
Shapes
§14.11: Shapes
Beyond the Labels, TextFields, and other
kinds of nodes (which we’ll get to in due time)
that the user will interact with as part of our
interface, sometimes our GUIs need a little
“artwork”
Shapes let us draw on a pane
§14.11: Shapes
Liang shows us 8 shapes we can use to dress up
our panes:
§14.11: Shapes
All of the shapes have some common properties:
fill (color)
stroke (line color)
strokeWidth (how heavy the stroke line is)
§14.11.1: Text
The Text shape lets us put text on a pane
“Wait, doesn’t a Label let us do the same thing?”
Well, yes and no.
They’re two different kinds of text, with two
different inheritance paths.
For more information, see here:
It’s pretty well summed up in the paragraph that starts
with “In general”.
§14.11.1: Text
Listing 14.14 (pp. 561 – 562) shows placing
three Text shapes on a pane, each time using
the (double, double, String) form of the
constructor to specify the x and y locations for
the String.
The text we place as a Shape can have its color,
font (typeface, weight, size, and posture),
underline, and strikethrough properties set.
This is different from a Label’s JavaFX CSS properties
Once placed, we can move text by using setX()
and setY() to give it a new location
§14.11.2: Line
Listing 14.15 (pp. 562 – 563) shows how to draw
a pair of Line shapes on a pane
Each line is specified by its two endpoints:
startX, startY and endX, endY (all doubles, in
pixels)
§14.11.3: Rectangle
The Rectangle shape is specified by its top-left
corner (x, y) and its width and height.
Optionally, we can specify the arcWidth and
arcHeight (in pixels) of the corners, to create
rounded corners (arc measurements of 0 make
squared-off corners)
See Listing 14-16
and Figure 14.31
§14.11.4: Circle and Ellipse
The Circle and Ellipse shapes are very
similar, as you might expect
Both are specified by their center point (centerX,
centerY)
The Circle has a single radius
The Ellipse has two radii (radiusX & radiusY)
See
Listing 14.17
(pp. 566 – 7)
§14.11.5: Arc
An Arc is just part of an Ellipse
An Arc is specified by its center point, radii, start
angle (in degrees), and length (in degrees)
If the two radii are equal, then it’s a circular arc
Angles may be negative (clockwise sweep)
§14.11.5: Arc
Once specified, an Arc can be drawn in any of
three styles: ArcType.OPEN, ArcType.CHORD, or
ArcType.ROUND
See Listing 14.18 (pp. 568 – 569) for the code
§14.11.6: Polygon and
Polyline
The Polygon and Polyline shapes are
identical, except that the Polyline isn’t closed
Both are specified by a list of (x, y) pairs
§14.11.6: Polygon and
Polyline
If we know all of the points up-front, we can
specify them as a variable-length parameter list:
Polygon p = new Polygon(x1, y1, x2, y2, …);
If we don’t know all of the points a priori, the
Polygon exposes an ObservableList to which
we can add points (i.e., generate the points on-
the-fly and add them to the list as we go)
This latter approach is taken by the program to create
a hexagon (Listing 14.19, pp. 570 – 1, and next slide)
§14.11.6: Polygon and
Polyline
Pane pane = new Pane(); // create a pane
Polygon polygon = new Polygon(); // create a polygon
pane.getChildren().add(polygon); // add the polygon to the pane
polygon.setFill(Color.WHITE); // polygon will be filled in white
polygon.setStroke(Color.BLACK); // with a black border
ObservableList<Double> list = polygon.getPoints(); // get its vertex list
final double WIDTH = 200, HEIGHT = 200; // See Fig. 14.40 (a)
double centerX = WIDTH / 2, centerY = HEIGHT / 2; //
double radius = Math.min(WIDTH, HEIGHT) * 0.4; //
Any Questions?