Unit 5 Material
Unit 5 Material
JavaFX is one of the Java’s client platforms and GUI framework. JavaFX provides a
powerful, streamlined, flexible framework that simplifies the creation of modern, visually
exciting GUIs.
The original version of JavaFX was built on a scripting language called JavaFX Script, which
has since been discontinued. Starting with the release of JavaFX 2.0, JavaFX has been
developed using Java itself and now offers a comprehensive API. Additionally, JavaFX
supports FXML, a markup language that can be used (though it is not mandatory) to define
the user interface.
JavaFX vs Swings
JavaFX Swing
Modern library for rich, media-intensive Legacy library for basic desktop
GUIs. applications.
Supports CSS for styling and FXML for
Requires manual coding for customization.
declarative UI.
Built-in support for 2D/3D graphics, Limited graphics capabilities, no media
animations, and multimedia. support.
Actively developed as a standalone module. No active development; considered legacy.
Can embed Swing components using Cannot embed JavaFX components; less
SwingNode. flexible.
Stage:
A Stage represents the primary window or container for a JavaFX application.
It's like the "frame" in which the entire user interface is displayed.
The primary stage is provided by JavaFX and is created automatically when the
application starts. You can also create additional stages for pop-ups or secondary
windows.
Important methods:
o setTitle(String title): Sets the title of the window.
o setScene(Scene scene): Assigns a scene to the stage.
o show(): Makes the stage visible.
o close(): Closes the stage.
Scene:
A Scene represents the content inside a stage. It serves as the container for all visual
elements (like buttons, labels, and layouts).
It is constructed using a root node, which is usually a layout container (e.g., VBox,
HBox, Pane).
A stage can only display one scene at a time, but you can switch scenes dynamically.
Important methods:
o setRoot(Parent root): Sets or changes the root node.
o setFill(Paint color): Sets the background fill color of the scene.
o getWidth() and getHeight(): Retrieve the dimensions of the scene.
Nodes:
A Node is the fundamental building block of a JavaFX user interface. Each visual
element in a JavaFX application (e.g., buttons, labels, shapes, etc.) is a subclass of the
Node class.
Nodes can represent graphical elements, shapes, text, images, or even entire
containers (layouts).
Every node has properties such as:
o Position and Size: layoutX, layoutY, width, height
o Transforms: rotate, scaleX, translateY, etc.
o Style: setStyle(String css)
o Event Handling: Nodes can respond to user interactions like mouse clicks or
key presses.
Scene Graph:
The Scene Graph is a hierarchical data structure that represents all the elements in a
JavaFX scene.
It is organized as a tree, with a single root node and child nodes branching out.
Parent nodes (like layouts) can have children, while leaf nodes (like a button or a
shape) cannot have children.
The Scene Graph forms the structure of the UI, ensuring a logical and organized
arrangement of nodes.
Characteristics Scene Graph:
Hierarchy: Nodes are arranged in a parent-child relationship. The root node is at the
top of the hierarchy.
Traversal: Operations on the scene graph, like rendering or event dispatching, traverse
this hierarchical structure.
Dynamic Updates: You can add, remove, or modify nodes dynamically, and the UI
will update accordingly.
Layouts
1. Types of Layouts:
JavaFX provides several built-in layout panes, such as Pane, HBox, VBox, GridPane,
BorderPane, StackPane, and FlowPane. Each serves a specific purpose in organizing UI
components.
2. Automatic Layout Management:
Layouts in JavaFX automatically resize and reposition their children based on the available
space and the child nodes' properties, like maxWidth, maxHeight, and alignment.
3. Nested Layouts:
Layouts can be nested to create complex UI designs. For instance, you can place an HBox
inside a GridPane or use a StackPane within a BorderPane.
4. Responsive Design:
JavaFX layouts are designed to adapt to changes in the window size. Containers like
GridPane supports flexible grid resizing, making it easier to create responsive applications.
The Application class in JavaFX is the entry point for JavaFX applications. It provides a
framework for the JavaFX runtime to launch and manage the application's lifecycle.
start(Stage primaryStage):
The main entry point for a JavaFX application.
Called after init() and is responsible for setting up the primary stage and the UI.
You must override this method in your subclass of Application.
The primaryStage represents the main window of the application.
Example: Setting the scene, adding components, and displaying the stage.
stop():
Called when the application is about to shut down.
Used for cleaning up resources, saving application state, or closing connections.
Can be triggered by the user closing the application or programmatically using
[Link]().
Here, args is a possibly empty list of strings that typically specify command-line arguments.
When called, launch( ) causes the application to be constructed, followed by calls to init( )
and start( ). The launch( ) method will not return until after the application has terminated.
This version of launch( ) starts the subclass of Application from which launch( ) is called.
A JavaFX Application Skeleton(Demonstration of life cycle methods)
All JavaFX applications share the same basic skeleton. In addition to showing the general
form of a JavaFX application, the skeleton also illustrates how to launch the application and
demonstrates when the life-cycle methods are called. A message noting when each life-cycle
method is called is displayed on the console. The complete skeleton is shown here:
Label(String str)
Here, str is the string that is displayed.
Once you have created a label (or any other control), it must be added to the scene’s content,
which means adding it to the scene graph. To do this, you will first call getChildren( ) on the
root node of the scene graph. It returns a list of the child nodes in the form of an
ObservableList<Node>. ObservableList is packaged in [Link], and it inherits
[Link]. Using the returned list of child nodes, you can add the label to the list by
calling add( ), passing in a reference to the label.
Example:
// Demonstrate a JavaFX label.
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
public class JavaFXLabelDemo extends Application {
public static void main(String[] args) {
// Start the JavaFX application by calling launch().
launch(args);
}
// Override the start() method.
public void start(Stage myStage) {
// Give the stage a title.
[Link]("Demonstrate a JavaFX label.");
// Use a FlowPane for the root node.
FlowPane rootNode = new FlowPane();
// Create a scene.
Scene myScene = new Scene(rootNode, 300, 200);
// Set the scene on the stage.
[Link](myScene);
// Create a label.
Label myLabel = new Label("This is a JavaFX label");
// Add the label to the scene graph.
[Link]().add(myLabel);
// Show the stage and its scene.
[Link]();
}
}
This program produces the following window:
ObservableList provides a method called addAll( ) that can be used to add two or more
children to the scene graph in a single call. To remove a control from the scene graph, call
remove( ) on the ObservableList. For example,
[Link]().remove(myLabel);
removes myLabel from the scene.
Button defines three constructors. The one we will use is shown here:
Button(String str)
In this case, str is the message that is displayed in the button. When a button is pressed, an
ActionEvent is generated. ActionEvent is packaged in [Link]. You can register a
listener for this event by using setOnAction( ), which has this general form:
Here, handler is the handler being registered. We can use an anonymous I nner class or
lambda expression for the handler. The setOnAction( ) method sets the property onAction,
which stores a reference to the handler.
package application;
JavaFX’s graphics methods are found in the GraphicsContext class, which is part of
[Link]. These methods can be used to draw directly on the surface of a canvas,
which is encapsulated by the Canvas class in [Link]. When you draw something,
such as a line, on a canvas, JavaFX automatically renders it whenever it needs to be
redisplayed.
Before you can draw on a canvas, you must perform two steps. First, you must create a
Canvas instance. Second, you must obtain a GraphicsContext object that refers to that
canvas. You can then use the GraphicsContext to draw output on the canvas. The Canvas
class is derived from Node; thus it can be used as a node in a scene graph.
Canvas defines two constructors. One is the default constructor, and the other is the one
shown here:
GraphicsContext getGraphicsContext2D( )
GraphicsContext defines a large number of methods that draw shapes, text, and images, and
support effects and transforms. A few of its methods are described here.
It draws a line from startX, startY to endX,endY, using the current stroke, which can be a
solid color or some more complex style.
To draw a rectangle, use either strokeRect( ) or fillRect( ), shown here:
The upper-left corner of the rectangle is at topX, topY. The width and height parameters
specify its width and height. The strokeRect( ) method draws the outline of a rectangle using
stroke, and fillRect( ) fills the rectangle with the current fill. The current fill can be as simple
as a solid color or something more complex.
To draw an ellipse, use either strokeOval( ) or fillOval( ), shown next:
The upper-left corner of the rectangle that bounds the ellipse is at topX, topY. The width and
height parameters specify its width and height. The strokeOval( ) method draws the outline
of an ellipse using the current stroke, and fillOval( ) fills the oval with the current fill. To
draw a circle, pass the same value for width and height.
You can draw text on a canvas by using the strokeText( ) and fillText( ) methods. We will
use this version of fillText( ):
It displays str starting at the location specified by topX, topY, filling the text with the current
fill. You can set the font and font size of the text being displayed by using setFont( ). You
can obtain the font used by the canvas by calling getFont( ). By default, the system font is
used. You can create a new font by constructing a Font object. Font is packaged in
[Link]. For example, you can create a default font of a specified size by using this
constructor:
Font(double fontSize)
Here, fontSize specifies the size of the font.
You can specify the fill and stroke using these two methods defined by Canvas:
void setFill(Paint newFill)
void setStroke(Paint newStroke)
Notice that the parameter of both methods is of type Paint. This is an abstract class packaged
in [Link]. Its subclasses define fills and strokes. The one we will use is Color,
which simply describes a solid color. Color defines several static fields that specify a wide
array of colors, such as [Link], [Link], [Link], and so on.
Exploring JavaFXControls
Image(String url)
Here, url specifies a URL or a path to a file that supplies the image. The argument is assumed
to refer to a path if it does not constitute a properly formed URL. Otherwise, the image is
loaded from the URL. The examples that follow will load images from files on the local
filesystem. Other constructors let you specify various options, such as the image’s width and
height. One other point: Image is not derived from Node. Thus, it cannot, itself, be part of a
scene graph. Once you have an Image, you will use ImageView to display it. ImageView is
derived from Node, which means that it can be part of a scene graph. ImageView defines
three constructors. The first one we will use is shown here:
ImageView(Image image)
This constructor creates an ImageView that uses image for its image. Putting the preceding
discussion into action, here is a program that loads an image of an hourglass and displays it
via ImageView. The hourglass image is contained in a file called [Link], which is
assumed to be in the local directory.
// Load and display an image.
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
public class ImageDemo extends Application {
public static void main(String[] args) {
// Start the JavaFX application by calling launch().
launch(args);
}
// Override the start() method.
public void start(Stage myStage) {
// Give the stage a title.
[Link]("Display an Image");
// Use a FlowPane for the root node.
FlowPane rootNode = new FlowPane();
// Use center alignment.
[Link]([Link]);
// Create a scene.
Scene myScene = new Scene(rootNode, 300, 200);
// Set the scene on the stage.
[Link](myScene);
// Create an image.
Image hourglass = new Image("[Link]");
// Create an image view that uses the image.
ImageView hourglassIV = new ImageView(hourglass);
// Add the image to the scene graph.
[Link]().add(hourglassIV);
// Show the stage and its scene.
[Link]();
}
}
Sample output from the program is shown here:
In the program, pay close attention to the following sequence that loads the image andthen
creates an ImageView that uses that image:
// Create an image.
Image hourglass = new Image("[Link]");
// Create an image view that uses the image.
ImageView hourglassIV = new ImageView(hourglass);
As explained, an image by itself cannot be added to the scene graph. It must first beembedded
in an [Link] cases in which you won’t make further use of the image, you can specify
a URL orfilename when creating an ImageView. In this case, there is no need to explicitly
create anImage. Instead, an Image instance containing the specified image is constructed
automaticallyand embedded in the ImageView. Here is the ImageView constructor that does
this:
ImageView(String url)
Here, url specifies the URL or the path to a file that contains the image.
Here, str specifies the text message and image specifies the image. Notice that the image is of
type Node. This allows great flexibility in the type of image added to the label, but for our
purposes, the image type will be ImageView. Here is a program that demonstrates a label
that includes a graphic. It creates a label that displays the string "Hourglass" and shows the
image of an hourglass that is loaded from
the [Link] file.
// Demonstrate an image in a label.
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
public class LabelImageDemo extends Application {
public static void main(String[] args) {
// Start the JavaFX application by calling launch().
launch(args);
}
// Override the start() method.
public void start(Stage myStage) {
// Give the stage a title.
[Link]("Use an Image in a Label");
// Use a FlowPane for the root node.
FlowPane rootNode = new FlowPane();
// Use center alignment.
[Link]([Link]);
// Create a scene.
Scene myScene = new Scene(rootNode, 300, 200);
// Set the scene on the stage.
[Link](myScene);
// Create an ImageView that contains the specified image.
ImageView hourglassIV = new ImageView("[Link]");
// Create a label that contains both an image and text.
Label hourglassLabel = new Label("Hourglass", hourglassIV);
// Add the label to the scene graph.
[Link]().add(hourglassLabel);
// Show the stage and its scene.
[Link]();
}
}
Here is the window produced by the program:
As you can see, both the image and the text are displayed. Notice that the text is to the right
of the image. This is the default. You can change the relative positions of the image and text
by calling setContentDisplay( ) on the label. It is shown here:
final void setContentDisplay(ContentDisplay position)
The value passed to position determines how the text and image is displayed. It must be one
of these values, which are defined by the ContentDisplay enumeration:
With the exception of TEXT_ONLY and GRAPHIC_ONLY, the values specify the
location of the image. For example, if you add this line to the preceding program:
[Link]([Link]); the image of the hourglass will be
above the text, as shown here:
The other two values let you display either just the text or just the image. This might be
useful if your application wants to use an image at some times, and not at others, for example.
(If you want only an image, you can simply display it without using a label, as described in
the previous section.)You can also add an image to a label after it has been constructed by
using the setGraphic( ) method. It is shown here:
Here, str specifies the text that is displayed within the button and image specifies the image.
You can specify the position of the image relative to the text by using
setContentDisplay( )in the same way as just described for Label. Here is an example that
displays two buttons that contain images. The first shows an hourglass. The second shows an
analog clock. When a button is pressed, the selected timepiece is reported. Notice that the text
is displayed beneath the image.
// Use an image with a button.
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
public class ButtonImageDemo extends Application {
Label response;
public static void main(String[] args) {
// Start the JavaFX application by calling launch().
launch(args);
}
// Override the start() method.
public void start(Stage myStage) {
// Give the stage a title.
[Link]("Use Images with Buttons");
// Use a FlowPane for the root node. In this case,
// vertical and horizontal gaps of 10.
FlowPane rootNode = new FlowPane(10, 10);
// Center the controls in the scene.
[Link]([Link]);
// Create a scene.
Scene myScene = new Scene(rootNode, 250, 450);
// Set the scene on the stage.
[Link](myScene);
// Create a label.
response = new Label("Push a Button");
// Create two image-based buttons.
Button btnHourglass = new Button("Hourglass",new ImageView("[Link]"));
Button btnAnalogClock = new Button("Analog Clock", new ImageView("[Link]"));
// Position the text under the image.
[Link]([Link]);
[Link]([Link]);
// Handle the action events for the hourglass button.
[Link](new EventHandler<ActionEvent>() {
public void handle(ActionEvent ae) {
[Link]("Hourglass Pressed");
}
});
// Handle the action events for the analog clock button.
[Link](new EventHandler<ActionEvent>() {
public void handle(ActionEvent ae) {
[Link]("Analog Clock Pressed");
}
});
// Add the label and buttons to the scene graph.
[Link]().addAll(btnHourglass, btnAnalogClock, response);
// Show the stage and its scene.
[Link]();
}
}
The output produced by this program is shown here:
If you want a button that contains only the image, pass a null string for the text when
constructing the button and then call setContentDisplay(), passing in the parameter
ContentDisplay.GRAPHIC_ONLY. For example, if you make these modifications to
theprevious program, the output will look like this:
ToggleButton
A useful variation on the push button is called the toggle button. A toggle button looks just
like a push button, but it acts differently because it has two states: pushed and released. That
is, when you press a toggle button, it stays pressed rather than popping back up as a regular
push button does. When you press the toggle button a second time, it releases(pops up).
Therefore, each time a toggle button is pushed, it toggles between these two states. In
JavaFX, a toggle button is encapsulated in the ToggleButton class. Like Button,
ToggleButton is also derived from ButtonBase. It implements the Toggle interface, which
defines functionality common to all types of two-state buttons.
ToggleButton defines three constructors. This is the one we will use:
ToggleButton(String str)
Here, str is the text displayed in the button. Another constructor allows you to include an
image. Like other buttons, a ToggleButton generates an action event when it is pressed.
Because ToggleButton defines a two-state control, it is commonly used to let the user select
an option. When the button is pressed, the option is selected. When the button is released, the
option is deselected. For this reason, a program usually needs to determine the toggle button’s
state. To do this, use the isSelected( ) method, shown here:
RadioButton
Another type of button provided by JavaFX is the radio button. Radio buttons are a group of
mutually exclusive buttons, in which only one button can be selected at any time. To create a
radio button, we will use the following constructor:
RadioButton(String str)
Here, str is the label for the button. Like other buttons, when a RadioButton is used, an
action event is generated. Radio buttons must be configured into a group for their mutually
exclusive nature to be activated. Only one of the buttons in the group can be selected at any
time. For example, if a user presses a radio button in a group, any previously selected button
in that group is automatically deselected. A button group is created by the ToggleGroup
class, which is packaged in [Link]. ToggleGroup provides only a default
constructor. Radio buttons are added to the toggle group by calling the setToggleGroup( )
method, defined by ToggleButton, on the button. It is shown here:
Here, tg is a reference to the toggle button group to which the button is added. After all radio
buttons have been added to the same group, their mutually exclusive behavior will be
enabled. In general, when radio buttons are used in a group, one of the buttons is selected
when the group is first displayed in the GUI. Here are two ways to do this.
First, you can call setSelected( ) on the button that you want to select. It is defined by
ToggleButton (which is a superclass of RadioButton). It is shown here:
void fire( )
This method results in an action event being generated for the button if the button was
previously not selected.
There are a number of different ways to use radio buttons. Perhaps the simplest is to simply
respond to the action event that is generated when one is selected. The following program
shows an example of this approach. It uses radio buttons to allow the user to select a type of
transportation.
// A simple demonstration of Radio Buttons. This program responds to the action events
generated by a radio button selection. It also shows how to fire the button under program
control.
package application;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
public class RadioButtonDemo extends Application {
Label response;
public static void main(String[] args) {
//Start the JavaFX application by calling launch().
launch(args);
}
//Override the start() method.
public void start(Stage myStage) {
//Give the stage a title.
[Link]("Demonstrate Radio Buttons");
//Use a FlowPane for the root node. In this case, vertical and horizontal gaps of 10.
FlowPane rootNode = new FlowPane(10, 10);
//Center the controls in the scene.
[Link]([Link]);
//Create a scene.
Scene myScene = new Scene(rootNode, 220, 120);
//Set the scene on the stage.
[Link](myScene);
//Create a label that will report the selection.
response = new Label("Select transport");
//Create the radio buttons.
RadioButton rbTrain = new RadioButton("Train");
RadioButton rbCar = new RadioButton("Car");
RadioButton rbPlane = new RadioButton("Airplane");
//Create a toggle group.
ToggleGroup tg = new ToggleGroup();
//Add each button to a toggle group.
[Link](tg);
[Link](tg);
[Link](tg);
//Handle action events for the radio buttons.
[Link]((ae)-> {
[Link]("Transport selected is train.");
});
[Link]((ae)-> {
[Link]("Transport selected is car.");
});
[Link]((ae)-> {
[Link]("Transport selected is airplane.");
});
//Fire the event for the first selection. This causes that radio button to be selected and an
action //event for that button to occur.
[Link]();
//Add the label and buttons to the scene graph.
[Link]().addAll(rbTrain, rbCar, rbPlane, response);
//Show the stage and its scene.
[Link]();
}
}
Sample output is shown here:
/* This radio button example demonstrates how the currently selected button in a group can
be obtained under program control, when it is needed, rather than responding to action or
change events. In this example, no events related to the radio buttons are handled. Instead, the
current selection is simply obtained when the Confirm Transport Selection push button is
pressed.*/
package application;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
public class RadioButtonDemo2 extends Application {
Label response;
ToggleGroup tg;
public static void main(String[] args) {
// Start the JavaFX application by calling launch().
launch(args);
}
// Override the start() method.
public void start(Stage myStage) {
// Give the stage a title.
[Link]("Demonstrate Radio Buttons");
// Use a FlowPane for the root node. In this case, vertical and horizontal gaps of 10.
FlowPane rootNode = new FlowPane(10, 10);
// Center the controls in the scene.
[Link]([Link]);
// Create a scene.
Scene myScene = new Scene(rootNode, 500, 400);
// Set the scene on the stage.
[Link](myScene);
// Create two labels.
Label choose = new Label(" Select a Transport Type ");
response = new Label("No transport confirmed");
// Create push button used to confirm the selection.
Button btnConfirm = new Button("Confirm Transport Selection");
// Create the radio buttons.
RadioButton rbTrain = new RadioButton("Train");
RadioButton rbCar = new RadioButton("Car");
RadioButton rbPlane = new RadioButton("Airplane");
// Create a toggle group.
tg = new ToggleGroup();
// Add each button to a toggle group.
[Link](tg);
[Link](tg);
[Link](tg);
// Initially select one of the radio buttons.
[Link](true);
// Handle action events for the confirm button.
[Link]((ae)->{
// Get the radio button that is currently selected.
RadioButton rb = (RadioButton) [Link]();
// Display the selection.
[Link]([Link]() + " is confirmed.");
});
// Use a separator to better organize the layout.
Separator separator = new Separator();
[Link](500);
// Add the label and buttons to the scene graph.
[Link]().addAll(choose,rbTrain,rbCar,rbPlane,separator,btnConfirm,response);
// Show the stage and its scene.
[Link]();
}
}
The output from the program is shown here:
Inside the action event handler for the btnConfirm button, notice that the selected radio
button is obtained by the following line:
RadioButton rb = (RadioButton) [Link]();
It returns a reference to the Toggle that is selected. In this case, the return value is cast to
RadioButton because this is the type of button in the group. The second thing to notice is the
use of a visual separator, which is created by this sequence:
Exercise 1
package example;
/
***************************************************************************
**
* (Traffic lights) Write a program that simulates a traffic light. The program *
* lets the user select one of three lights: red, yellow, or green. When a radio *
* button is selected, the light is turned on. Only one light can be on at a time *
*. No light is on when the program starts. *
***************************************************************************
******/
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
// Create a rectangle
Rectangle rectangle = new Rectangle();
[Link]([Link]);
[Link](30);
[Link](100);
[Link]([Link]);
[Link](2);
StackPane stopSign = new StackPane(rectangle, paneForCircles);
// Create a hbox
HBox paneForRadioButtons = new HBox(5);
[Link]([Link]);
[Link](e -> {
if ([Link]()) {
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
}
});
[Link](e -> {
if ([Link]()) {
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
}
});
CheckBox(String str)
It creates a check box that has the text specified by str as a label. As with other buttons, a
CheckBox generates an action event when it is selected. Here is a program that demonstrates
check boxes. It displays check boxes that let the user select various deployment options,
which are Web, Desktop, and Mobile. Each time a check box state changes, an action event is
generated and handled by displaying the new state (selected or cleared) and by displaying a
list of all selected boxes.
package application;
package application;
The operation of this program is straightforward. Each time a check box is changed, an action
command is generated. To determine if the box is checked or unchecked, the isSelected( )
method is called. As mentioned, by default, CheckBox implements two states: checked and
unchecked. If you want to add the indeterminate state, it must be explicitly enabled. To do
this, call setAllowIndeterminate( ), shown here:
In this case, if enable is true, the indeterminate state is enabled. Otherwise, it is disabled.
When the indeterminate state is enabled, the user can select between checked, unchecked, and
indeterminate. You can determine if a check box is in the indeterminate state by calling
isIndeterminate( ), shown here:
[Link](true);
[Link](true);
[Link](true);
Next, handle the indeterminate state inside the action event handlers. For example, here isthe
modified handler for cbWeb:
[Link](new EventHandler<ActionEvent>() {
public void handle(ActionEvent ae) {
if([Link]())
[Link]("Web deployment indeterminate.");else if([Link]())
[Link]("Web deployment selected.");
else
[Link]("Web deployment cleared.");
showAll();
}
});
Now, all three states are tested. Update the other two handlers in the same way. After making
these changes, the indeterminate state can be selected, as this sample output shows:
ListView
Another commonly used control is the list view, which in JavaFX is encapsulated by
ListView. List views are controls that display a list of entries from which you can select one
or more. Because of their ability to make efficient use of limited screen space, list views are
popular alternatives to other types of selection controls.
ListView is a generic class that is declared like this:
class ListView<T>
Here, T specifies the type of entries stored in the list view. Often, these are entries of type
String, but other types are also allowed.
ListView defines two constructors. The first is the default constructor, which creates an
empty ListView. The second lets you specify the list of entries in the list. It is shown here:
ListView(ObservableList<T>list)
Here, list specifies a list of the items that will be displayed. It is an object of type
ObservableList, which defines a list of observable objects. It inherits [Link]. Thus, it
supports the standard collection methods. ObservableList is packaged in [Link].
Probably the easiest way to create an ObservableList for use in a ListView is to use the
factory method observableArrayList( ), which is a static method defined by the
FXCollections class (which is also packaged in [Link]). The version we will use
is shown here:
In this case, E specifies the type of elements, which are passed via elements. By default, a
ListView allows only one item in the list to be selected at any one time.
However, you can allow multiple selections by changing the selection mode. For now, we
will use the default, single-selection model. Although ListView provides a default size,
sometimes you will want to set the preferred height and/or width to best match your needs.
One way to do this is to call the setPrefHeight( ) and setPrefWidth( ) methods, shown here:
There are two basic ways in which you can use a ListView. First, you can ignore events
generated by the list and simply obtain the selection in the list when your program needs it.
Second, you can monitor the list for changes by registering a change listener. This lets you
respond each time the user changes a selection in the list. This is the approach used here. To
listen for change events, you must first obtain the selection model used by the ListView. This
is done by calling getSelectionModel( ) on the list. It is shown here:
It returns a reference to the model. MultipleSelectionModel is a class that defines the model
used for multiple selections, and it inherits SelectionModel. However, multiple selections are
allowed in a ListView only if multiple-selection mode is turned on. Using the model returned
by getSelectionModel( ), you will obtain a reference to the selected item property that
defines what takes place when an element in the list is selected. This is done by calling
selectedItemProperty( ), shown next:
In the program, pay special attention to how the ListView is constructed. First, an
ObservableList is created by this line:
ObservableList<String> transportTypes =
[Link]( "Train", "Car", "Airplane" );
It uses the observableArrayList( ) method to create a list of strings. Then, the
ObservableList
is used to initialize a ListView, as shown here:
ListView<String> lvTransport = new ListView<String>(transportTypes);
The program then sets the preferred width and height of the [Link], notice how the
selection model is obtained for lvTransport:
MultipleSelectionModel<String> lvSelModel =[Link]();
ListView Scrollbars
One very useful feature of ListView is that when the number of items in the list exceeds the
number that can be displayed within its dimensions, scrollbars are automatically added. For
example, if you change the declaration of transportTypes so that it includes "Bicycle"
and"Walking", as shown here:
ObservableList<String> transportTypes =
[Link]( "Train", "Car", "Airplane",
"Bicycle", "Walking" );
the lvTransport control now looks like the one shown here:
ObservableList<T> getSelectedItems( )
[Link]().setSelectionMode([Link]);
It enables multiple-selection mode for lvTransport. Finally, replace the change eventhandler
with the one shown here:
[Link]().addListener(
new ChangeListener<String>() {
public void changed(ObservableValue<? extends String> changed,String oldVal, String
newVal) {
String selItems = "";
ObservableList<String> selected =
[Link]().getSelectedItems();
// Display the selections.
for(int i=0; i < [Link](); i++)
selItems += "\n " + [Link](i);
[Link]("All transports selected: " + selItems);
}
});
After making these changes, the program will display all selected forms of transports, as
the following output shows:
Assignments
ComboBox
A control related to the list view is the combo box, which is implemented in JavaFX by the
ComboBox class. A combo box displays one selection, but it will also display a drop-down
list that allows the user to select a different item. You can also allow the user to edit a
selection.
ComboBox inherits ComboBoxBase, which provides much of its functionality. Unlike the
ListView, which can allow multiple selections, ComboBox is designed for single-selection.
ComboBox is a generic class that is declared like this:
class ComboBox<T>
Here, T specifies the type of entries. Often, these are entries of type String, but other types
are also allowed.
ComboBox defines two constructors. The first is the default constructor, which creates an
empty ComboBox. The second lets you specify the list of entries. It is shown here:
ComboBox(ObservableList<T> list)
In this case, list specifies a list of the items that will be displayed. It is an object of type
ObservableList, which defines a list of observable objects. ObservableList inherits
[Link]. An easy way to create an ObservableList is to use the factory method
observableArrayList( ), which is a static method defined by the FXCollections class.
A ComboBox generates an action event when its selection changes. It will also generate a
change event. Alternatively, it is also possible to ignore events and simply obtain the current
selection when needed.
You can obtain the current selection by calling getValue( ), shown here:
final T getValue( )
If the value of a combo box has not yet been set (by the user or under program control), then
getValue( ) will return null. To set the value of a ComboBox under program control,
call setValue( ):
The following program demonstrates a combo box by reworking the previous list view
example. It handles the action event generated by the combo box.
If enable is true, editing is enabled. Otherwise, it is disabled. To see the effects of editing, add
this line to the preceding program:
[Link](true);
After making this addition, you will be able to edit the selection.
TextField
TextField allows one line of text to be entered. Thus, it is useful for obtaining names, ID
strings, addresses, etc. Like all text controls, TextField inherits TextInputControl, which
defines much of its functionality.
TextField defines two constructors. The first is the default constructor, which creates an
empty text field that has the default size. The second lets you specify the initial contents of
the field. Here, we will use the default constructor.
Although the default size is sometimes adequate, often you will want to specify its size. This
is done by calling setPrefColumnCount( ), shown here:
You can also select a portion of the text under program control.
One especially useful TextField option is the ability to set a prompting message inside the
text field when the user attempts to use a blank field. To do this, call setPromptText( ), shown
here:
In this case, str is the string displayed in the text field when no text has been entered. It is
displayed using low-intensity (such as a gray tone).
When the user presses enter while inside a TextField, an action event is generated.
Although handling this event is often helpful, in some cases, your program will simply obtain
the text when it is needed, rather than handling action events. Both approaches are
demonstrated by the following program. It creates a text field that requests a search string.
When the user presses enter while the text field has input focus, or presses the Get Search
String button, the string is obtained and displayed. Notice that a prompting message is also
included.
PasswordField
PasswordField is a Text field that masks entered characters (the characters that are entered
are not shown to the user). It allows the user to enter a single-line of unformatted text, hence
it does not allow multi-line input.
// create a Passwordfield
PasswordField b =new PasswordField();
1. Output:
Exercise
package application;
//LOGIN PAGE WITH VALIDATION
import [Link];
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link];
import [Link];
public class LoginpageValidation extends Application {
//Start the JavaFX application by calling launch().
public static void main(String[] args) {
launch(args);
}
//Override the start() method.
public void start(Stage myStage) {
//Give the stage a title.
[Link]("Demonstrate a Toggle Button");
FlowPane rootNode = new FlowPane(100,10);
[Link]([Link]);
Scene myScene = new Scene(rootNode, 300, 300);
[Link](myScene);
Label response=new Label("enter username and password");
TextField t= new TextField("username");
PasswordField p= new PasswordField();
Button btnlogin=new Button("LOGIN");
[Link]((ae)-> {
if([Link]().equals("NITTE") && [Link]().equals("NITTE123"))
[Link]("LOGIN SUCCESSFUL. WELCOME "+
[Link]());
else [Link]("LOGIN FAILED. INVALID USERNAME OR
PASSWORD");
});
[Link]().addAll(t,p,btnlogin, response);
[Link]();
}
}
ScrollPane
Sometimes, the contents of a control will exceed the amount of screen space that you want to
give to it. Here are two examples: A large image may not fit within reasonable boundaries, or
you might want to display text that is longer than will fit within a small window. Whatever
the reason, JavaFX makes it easy to provide scrolling capabilities to any node in a scene
graph. This is accomplished by wrapping the node in a ScrollPane. When a ScrollPane is
used, scrollbars are automatically implemented that scroll the contents of the wrapped node.
No further action is required on your part.
ScrollPane defines two constructors. The first is the default constructor. The second lets you
specify a node that you want to scroll. It is shown here:
ScrollPane(Node content)
In this case, content specifies the information to be scrolled. When using the default
constructor, you will add the node to be scrolled by calling setContent( ). It is shown here:
NOTE You can also use setContent( ) to change the content being scrolled by the scroll pane.
Thus, what is being scrolled can be changed during the execution of your program. Although
a default size is provided, as a general rule, you will want to set the dimensions of the
viewport. The viewport is the viewable area of a scroll pane. It is the area in which the
content being scrolled is displayed. Thus, the viewport displays the visible portion of the
content. The scrollbars scroll the content through the viewport. Thus, by moving a scrollbar,
you change what part of the content is visible.
You can set the viewport dimensions by using these two methods:
In its default behavior, a ScrollPane will dynamically add or remove a scrollbar as needed.
For example, if the component is taller than the viewport, a vertical scrollbar is added. If the
component will completely fit within the viewport, the scrollbars are removed. One nice
feature of ScrollPane is its ability to pan the contents by dragging the mouse.
By default, this feature is off. To turn it on, use setPannable( ), shown here:
If enable is true, then panning is allowed. Otherwise, it is disabled. You can set the position
of the scrollbars under program control using setHvalue( ) and setVvalue( ), shown here:
The new horizontal position is specified by newHval, and the new vertical position is
specified by newVval. By default, scrollbar positions start at zero.
ScrollPane supports various other options. For example, it is possible to set the minimum and
maximum scrollbar positions. You can also specify when and if the scrollbars are shown by
setting a scrollbar policy. The current position of the scrollbars can be obtained by calling
The following program demonstrates ScrollPane by using one to scroll the contents
TreeView
TreeView presents a hierarchical view of data in a tree-like format. In this context, the term
hierarchical means some items are subordinate to others. For example, a tree is commonly
used to display the contents of a file system. In this case, the individual files are subordinate
to the directory that contains them. In a TreeView, branches can be expanded or collapsed on
demand by the user.
TreeView implements a conceptually simple, tree-based data structure. A tree begins with a
single root node that indicates the start of the tree. Under the root are one or more child nodes
There are two types of child nodes: leaf nodes (also called terminal nodes), which have no
children, and branch nodes, which form the root nodes of subtrees. A subtree is simply a tree
that is part of a larger tree. The sequence of nodes that leads from the root to specific node is
called a path.
One very useful feature of TreeView is that it automatically provides scrollbars when the size
of the tree exceeds the dimensions of the view. Although a fully collapsed tree might be quite
small, its expanded form may be quite large. By automatically adding scrollbars as needed,
TreeView lets you use a smaller space than would ordinarily be possible.
TreeView is a generic class that is defined like this:
class TreeView<T>
Here, T specifies the type of value held by an item in the tree. Often, this will be of type
String. TreeView defines two constructors. This is the one we will use:
TreeView(TreeItem<T> rootNode)
Here, rootNode specifies the root of the tree. Because all nodes descend from the root, it is
the only one that needs to be passed to TreeView.
The items that form the tree are objects of type TreeItem. At the outset, it is important to state
that TreeItem does not inherit Node. Thus, TreeItems are not general-purpose objects. They
can be used in a TreeView, but not as stand-alone controls. TreeItem is a generic class, as
shown here:
class TreeItem<T>
Here, T specifies the type of value held by the TreeItem.
Before you can use a TreeView, you must construct the tree that it will display. To do this,
you must first create the root. Next, add other nodes to that root. You do this by calling either
add( ) or addAll( ) on the list returned by getChildren( ). These other nodes can be leaf nodes
or subtrees. After the tree has been constructed, you create the TreeView by passing the root
node to its constructor.
You can handle selection events in the TreeView in a way similar to the way that you handle
them in a ListView, through the use of a change listener. To do so, first, obtain the selection
model by calling getSelectionModel( ). Then, call selectedItemProperty( ) to obtain the
property for the selected item. On that return value, call addListener( ) to add a change
listener. Each time a selection is made, a reference to the new selection will be passed to the
changed( ) handler as the new value. (See ListView for more details on handling change
events.)
You can obtain the value of a TreeItem by calling getValue( ). You can also follow the tree
path of an item in either the forward or backward direction. To obtain the parent, call
getParent( ). To obtain the children, call getChildren( ).
The following example shows how to build and use a TreeView. The tree presents a
hierarchy of food. The type of items stored in the tree are strings. The root is labeled Food.
Under it are three direct descendent nodes: Fruit, Vegetables, and Nuts. Under Fruit are three
child nodes: Apples, Pears, and Oranges. Under Apples are three leaf nodes: Fuji, Winesap,
and Jonathan. Each time a selection is made, the name of the item is displayed.
Also, the path from the root to the item is shown. This is done by the repeated use of
getParent( ).
// Demonstrate a TreeView
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
public class TreeViewDemo extends Application {
Label response;
public static void main(String[] args) {
// Start the JavaFX application by calling launch().
launch(args);
}
// Override the start() method.
public void start(Stage myStage) {
// Give the stage a title.
[Link]("Demonstrate a TreeView");
// Use a FlowPane for the root node. In this case,
// vertical and horizontal gaps of 10.
FlowPane rootNode = new FlowPane(10, 10);
// Center the controls in the scene.
[Link]([Link]);
// Create a scene.
Scene myScene = new Scene(rootNode, 310, 460);
// Set the scene on the stage.
[Link](myScene);
// Create a label that will report the state of the
// selected tree item.
response = new Label("No Selection");
// Create tree items, starting with the root.
TreeItem<String> tiRoot = new TreeItem<String>("Food");
// Now add subtrees, beginning with fruit.
TreeItem<String> tiFruit = new TreeItem<String>("Fruit");
// Construct the Apple subtree.
TreeItem<String> tiApples = new TreeItem<String>("Apples");
// Add child nodes to the Apple node.
[Link]().add(new TreeItem<String>("Fuji"));
[Link]().add(new TreeItem<String>("Winesap"));
[Link]().add(new TreeItem<String>("Jonathan"));
// Add varieties to the fruit node.
[Link]().add(tiApples);
[Link]().add(new TreeItem<String>("Pears"));
[Link]().add(new TreeItem<String>("Oranges"));
// Finally, add the fruit node to the root.
[Link]().add(tiFruit);
// Now, add vegetables subtree, using the same general process.
TreeItem<String> tiVegetables = new TreeItem<String>("Vegetables");
[Link]().add(new TreeItem<String>("Corn"));
[Link]().add(new TreeItem<String>("Peas"));
[Link]().add(new TreeItem<String>("Broccoli"));
[Link]().add(new TreeItem<String>("Beans"));
[Link]().add(tiVegetables);
// Likewise, add nuts subtree.
TreeItem<String> tiNuts = new TreeItem<String>("Nuts");
[Link]().add(new TreeItem<String>("Walnuts"));
[Link]().add(new TreeItem<String>("Peanuts"));
[Link]().add(new TreeItem<String>("Pecans"));
[Link]().add(tiNuts);
// Create tree view using the tree just created.
TreeView<String> tvFood = new TreeView<String>(tiRoot);
// Get the tree view selection model.
MultipleSelectionModel<TreeItem<String>> tvSelModel =
[Link]();
// Use a change listener to respond to a selection within a tree view
[Link]().addListener(
new ChangeListener<TreeItem<String>>() {
public void changed(
ObservableValue<? extends TreeItem<String>> changed,
TreeItem<String> oldVal, TreeItem<String> newVal) {
// Display the selection and its complete path from the root.
if(newVal != null) {
// Construct the entire path to the selected item.
String path = [Link]();
TreeItem<String> tmp = [Link]();
while(tmp != null) {
path = [Link]() + " -> " + path;
tmp = [Link]();
}
// Display the selection and the entire path.
[Link]("Selection is " + [Link]() +
"\nComplete path is " + path);
}
}
});
// Add controls to the scene graph.
[Link]().addAll(tvFood, response);
// Show the stage and its scene.
[Link]();
}
}
Sample output is shown here:
There are two things to pay special attention to in this program. First, notice how the tree is
constructed. First, the root node is created by this statement:
TreeItem<String> tiRoot = new TreeItem<String>("Food");
Next, the nodes under the root are constructed. These nodes consist of the root nodes of
subtrees: one for fruit, one for vegetables, and one for nuts. Next, the leaves are added to
these subtrees. However, one of these, the fruit subtree, consists of another subtree that
contains varieties of apples. The point here is that each branch in a tree leads either to a leaf
or to the root of a subtree. After all of the nodes have been constructed, the root nodes of each
subtree are added to the root node of the tree. This is done by calling add( ) on the root node.
For example, this is how the Nuts subtree is added to tiRoot.
[Link]().add(tiNuts);
The process is the same for adding any child node to its parent node.
The second thing to notice in the program is the way the path from the root to the selected
node is constructed within the change event handler. It is shown here:
while(tmp != null) {
tmp = [Link]();
The code works like this: First, the value of the newly selected node is obtained. In this
example, the value will be a string, which is the node’s name. This string is assigned to the
path string. Then, a temporary variable of type TreeItem<String> is created and initialized to
refer to the parent of the newly selected node. If the newly selected node does not have a
parent, then tmp will be null. Otherwise, the loop is entered, within which each parent’s value
(which is its name in this case) is added to path. This process continues until the root node of
the tree (which has no parent) is found. Although the preceding shows the basic mechanism
required to handle a TreeView, it is important to point out that several customizations and
options are supported. TreeView is a powerful control that you will want to examine fully on
your own.
Introducing JavaFX Menus
Menu system.
Menu Basics
The JavaFX menu system is supported by a group of related classes packaged in
[Link].
To create a main menu for an application, you first need an instance of MenuBar. This class
is a container for menus. To the MenuBar you add instances of Menu. Each Menu object
defines a menu. That is, each Menu object contains one or more selectable items. The items
displayed by a Menu are objects of type MenuItem. Thus, a MenuItem defines a selection
that can be chosen by the user.
This enables one menu to be submenu of another. Menu defines three constructors.
Menu(String name)
It creates a menu that has the name specified by name. You can specify an image along with
text with this constructor:
Here, image specifies the image that is displayed. In all cases, the menu is empty until menu
items are added to it. Finally, you don’t have to give a menu a name when it is constructed.
Menu( )
In this case, you can add a name and/or image after the fact by calling setText( ) or
setGraphic( ).
Each menu maintains a list of menu items that it contains. To add an item to the menu,add
items to this list. To do so, first call getItems( ), shown here:
It returns the list of items currently associated with the menu. To this list, add menu items by
calling either add( ) or addAll( ). Among other actions, you can remove an item by calling
remove( ) and obtain the size of the list by calling size( ).
One other point: You can add a menu separator to the list of menu items, which is an object
of type SeparatorMenuItem. Separators help organize long menus by allowing you to group
related items together. A separator can also help set off an important item, such as the Exit
selection in a menu.
MenuItem
MenuItem encapsulates an element in a menu. This element can be either a selection linked to
some program action, such as Save or Close, or it can cause a submenu to be displayed.
MenuItem( )
MenuItem(String name)
The first creates an empty menu item. The second lets you specify the name of the item, and
the third enables you to include an image.
A MenuItem generates an action event when selected. You can register an action event
handler for such an event by calling setOnAction( ), just as you did when handling button
events. It is shown again for your convenience:
Here, handler specifies the event handler. You can fire an action event on a menu item by
calling fire( ).
MenuItem defines several methods. One that is often useful is setDisable( ), which you can
use to enable or disable a menu item. It is shown here:
As a general rule, the most commonly used menu is the main menu. This is the menu defined
by the menu bar, and it is the menu that defines all (or nearly all) of the functionality of an
application. As you will see, JavaFX streamlines the process of creating and managing the
main menu. Here, you will see how to construct a simple main menu. Subsequent sections
will show various options.
Constructing the main menu requires several steps. First, create the MenuBar instance that
will hold the menus. Next, construct each menu that will be in the menu bar. In general, a
menu is constructed by first creating a Menu object and then adding MenuItems to it. After
the menus have been created, add them to the menu bar. Then, the menu bar, itself, must be
added to the scene graph. Finally, for each menu item, you must add an action event handler
that responds to the action event fired when a menu item is selected.
Here is a program that creates a simple menu bar that contains three menus. The first is a
standard File menu that contains Open, Close, Save, and Exit selections.
The second menu is called Options, and it contains two submenus called Colors and
Priority.
The third menu is called Help, and it has one item: About. When a menu item is selected, the
name of the selection is displayed in a label.
// Demonstrate Menus
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
import [Link].*;
public class MenuDemo extends Application {
Label response;
public static void main(String[] args) {
// Start the JavaFX application by calling launch().
launch(args);
}
// Override the start() method.
public void start(Stage myStage) {
// Give the stage a title.
[Link]("Demonstrate Menus");
// Use a BorderPane for the root node.
BorderPane rootNode = new BorderPane();
// Create a scene.
Scene myScene = new Scene(rootNode, 300, 300);
// Set the scene on the stage.
[Link](myScene);
// Create a label that will report the selection.
response = new Label("Menu Demo");
// Create the menu bar.
MenuBar mb = new MenuBar();
// Create the File menu.
Menu fileMenu = new Menu("File");
MenuItem open = new MenuItem("Open");
MenuItem close = new MenuItem("Close");
MenuItem save = new MenuItem("Save");
MenuItem exit = new MenuItem("Exit");
[Link]().addAll(open, close, save,new SeparatorMenuItem(), exit);
// Add File menu to the menu bar.
[Link]().add(fileMenu);
// Create the Options menu.
Menu optionsMenu = new Menu("Options");
// Create the Colors submenu.
Menu colorsMenu = new Menu("Colors");
MenuItem red = new MenuItem("Red");
MenuItem green = new MenuItem("Green");
MenuItem blue = new MenuItem("Blue");
[Link]().addAll(red, green, blue);
[Link]().add(colorsMenu);
// Create the Priority submenu.
Menu priorityMenu = new Menu("Priority");
MenuItem high = new MenuItem("High");
MenuItem low = new MenuItem("Low");
[Link]().addAll(high, low);
[Link]().add(priorityMenu);
// Add a separator.
[Link]().add(new SeparatorMenuItem());
// Create the Reset menu item.
MenuItem reset = new MenuItem("Reset");
[Link]().add(reset);
// Add Options menu to the menu bar.
[Link]().add(optionsMenu);
// Create the Help menu.
Menu helpMenu = new Menu("Help");
MenuItem about = new MenuItem("About");
[Link]().add(about);
// Add Help menu to the menu bar.
[Link]().add(helpMenu);
// Create one event handler that will handle menu action events.
EventHandler<ActionEvent> MEHandler =
new EventHandler<ActionEvent>() {
public void handle(ActionEvent ae) {
String name = ((MenuItem)[Link]()).getText();
// If Exit is chosen, the program is terminated.
if([Link]("Exit")) [Link]();
[Link]( name + " selected");
}
};
// Set action event handlers for the menu items.
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
[Link](MEHandler);
// Add the menu bar to the top of the border pane and
// the response label to the center position.
[Link](mb);
[Link](response);
// Show the stage and its scene.
[Link]();
}
}
Sample output is shown here:
MenuDemo uses a BorderPane instance for the root node. It defines a window that has five
areas: top,bottom, left, right, and center. The following methods set the node assigned to
these areas: