Uploaded by lewismarley0

#Java Programming - JavaFX (Basic).pdf

advertisement
TEMPLATE
The main steps in developing a GUI application in JavaFX include:
1. Create the nodes needed
2. Organize these nodes into a pane (provides control over node position, and size)
3. Create a scene with the pane
4. Set the scene on a stage
5. Display the stage
public class AppName extends Application{
public void start(Stage primaryStage){
// Create a scene and place components on scene
// Place scene on stage
// Display stage
}
// Only necessary in IDEs with limited support for JavaFX
public static void main(String[] args){
Application.launch(args);
}
}
The diagrams below show some of the classes that play a key role in creating a GUI using
JavaFX and how they are related.
STAGE
1. setScene(Scene scene)
2. setTitle(String txt)
3. show()
4. hide()
5. close()
PARENT
Base class for all nodes with the capability to contain other nodes. Calling getChildren()
through it returns a list (ObservableList<Class> from the Collection class) through which
the following methods can then be invoked:
1. void add(Node node)
2. void addAll(Node… node)
3. void remove(Node node)
4. void clear(): removes all child nodes
5. int size(): returns the number of child nodes.
6. Class get(int index): returns the node at the specified index
NODE
Base class (abstract) for all objects (nodes => visual components) that can be added to a
scene. Some important methods of the Node class:
1. Parent getParent()
2. String getId()
3. void setId(String id): ID has to be unique within the scene graph
4. Node lookup(String id): searches the Node’s children for the one with id matching the
argument. The argument, id, must start with #.
5. String getStyle()
6. void setStyle(String style)
Note
Root node: the node that starts a scene graph
Branch node: node that has at least one child node
Leaf node: node that has no child node
Control: base class for label, button, check box, radio button, text field, text area etc.
This class provides the method: void setTooltip(Tooltip value). Where value = new
Tooltip(“hint to display”);
Shape: refers to a text, line, circle, ellipse, rectangle, arc, polygon, polyline, and so
on.
Other types of node include:
• Camera
• Canvas
• LightBase (Abstract)
• MadiaView
• Shape3D
• Subscene
• SwingNode: to allow the use of GUI components from javax.swing
SCENE
1.
Scene(Parent rootNode)
2.
Scene(Parent rootNode, double width, double height) // stage size = width x height
3.
void setRoot(Parent rootNode)
Note
Scene graph: a tree structure that contains all the nodes that make up a user interface.
IMAGE VIEW
ImageView imageName = new ImageView(new Image(“Image URL”));
LABEL
1. Label()
2. Label(String txt)
3. Label(String txt, Node image)
4. void setAlignment(Pos alignment)
alignment
=
Pos.BASELINE_CENTER,
BASELINE_LEFT,
BASELINE_RIGHT,
BOTTOM_CENTER,
BOTTOM_LEFT,
BOTTOM_RIGHT, CENTER, CENTER_LEFT, CENTER_RIGHT, TOP_CENTER, TOP_LEFT, TOP_RIGHT where Pos is an
enumeration constant.
5. void setUnderLine(boolean status)
BUTTON
1. Button()
2. Button(String txt)
3. void setText(String txt, Node image)
4. void setAlignment(Pos alignment) // alignment  static values from the class Pos.
5. void setUnderLine(boolean status)
RADIO BUTTON
1.
RadioButton()
2.
RadioButton(String text)
3.
void setSelected(boolean status)
4.
void setToggleGroup(ToggleGroup grp): add radio button to a mutually exclusive group
(grp).
-
grp = new ToggleGroup()
-
grp also provides getToggles() which returns ObservableList<Node>, thus providing
the opportunity add all mutually exclusive radio buttons to the group through the
method addAll(Node… radioButtons).
5.
void setAlignment(Pos alignment)
6.
void setUnderLine(boolean status): underline the label
7.
boolean isSelected()
8.
void setSelected(boolean status)
9.
void setText(String text)
10. String getText()
PROGRAM FOR ILLUSTRATION
import javafx.application.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.*;
public class ClickMe extends Application{
Button btn;
RadioButton eco, bus, fst;
@Override
public void start(Stage stage){
btn = new Button("SUBMIT YOUR FLIGHT CLASS");
btn.setOnAction(e -> buttonClick());
eco = new RadioButton("Economy Class");
eco.setSelected(true);
bus = new RadioButton("Business Class");
fst = new RadioButton("First Class");
// Make buttons mutually exclusive
ToggleGroup grp = new ToggleGroup();
grp.getToggles().addAll(eco, bus, fst);
// Alternative approach to making them mutually exclusive
eco.setToggleGroup(grp);
bus.setToggleGroup(grp);
fst.setToggleGroup(grp);
//
//
//
FlowPane pane = new FlowPane();
pane.getChildren().addAll(btn, eco, bus, fst);
Scene scene = new Scene(pane, 500, 100);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args){
Application.launch(args);
}
private void buttonClick() {
String choice = "Flight class chosen: ";
if(eco.isSelected())
choice += eco.getText();
else if(bus.isSelected())
choice += bus.getText();
else
choice += fst.getText();
System.out.println(choice);
}
}
OUTPUT
1. Run program
2. Click button
3. Select “Business Class” and click button
4. Select “First Class” and click button
5. Close window
CHECK BOX
1. CheckBox()
2. CheckBox(String text)
3. String getText(): returns the label of the text
4. boolean isSelected(): returns the state of the check box i.e. true  selected, false 
unselected
5. void setSelected(boolean status)
6. void setDisabled(Boolean status): true to disable, and false to enable.
PROGRAM TO ILLUSTRATE
import
import
import
import
import
javafx.application.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application{
Button btn;
CheckBox golf = new CheckBox("Golf"), chess = new CheckBox("Chess"),
football = new CheckBox("Football"), boxing = new CheckBox("Boxing");
@Override
public void start(Stage stage){
btn = new Button("SUBMIT FAVOURITE SPORT(S)");
btn.setOnAction(e -> buttonClick());
FlowPane pane = new FlowPane();
pane.getChildren().addAll(btn, golf, chess, football, boxing);
Scene scene = new Scene(pane, 500, 100);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args){
Application.launch(args);
}
private void buttonClick() {
String choice = "Favourite Sports Selected\n";
choice += golf.isSelected() ? golf.getText() + "\n" : "";
choice += chess.isSelected() ? chess.getText() + "\n" : "";
choice += football.isSelected() ? football.getText() + "\n" : "";
choice += boxing.isSelected() ? boxing.getText() + "\n" : "";
System.out.println(choice);
}
}
OUTPUT
TEXT FIELD
1. TextField()
2. TextField(String txt)
3. void setText(String text)
4. void setPromptText(String prompt)
5. String getText()
6. void setEditable(boolean status)
7. void setPrefColumnCount(int cols)
PASSWORD FIELD
PasswordField is the class to use if a text field is for a password. PasswordField extends
TextField.
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
javafx.application.*;
javafx.scene.Scene;
javafx.scene.control.*;
javafx.scene.layout.FlowPane;
javafx.stage.*;
public class ClickMe extends Application {
Button btn;
TextField username;
PasswordField password;
@Override
public void start(Stage stage) {
btn = new Button("CLICK ME");
btn.setOnAction(e -> btnClick());
username = new TextField();
password = new PasswordField();
FlowPane pane = new FlowPane();
pane.getChildren().addAll(
btn, new Label("Username: "), username, new Label("Password: "), password
);
Scene scene = new Scene(pane, 500, 50);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private void btnClick() {
System.out.println("DETAILS ENTERED\nUsername: "
+ username.getText()
+ "\nPassword: " + password.getText());
}
}
OUTPUT
1. Run the program
2. Provide username and password
3. Click the button
4. Close the window
TEXT AREA
1.
TextArea()
2.
TextArea(String text)
3.
void setWrapText(Boolean status): default value is false i.e. it doesn’t wrap.
4.
void setPrefColumnCount(int cols): controls the width of the area
5.
void setPrefRowCount(int rows): number of rows of text that should be visible at the
same time.
6.
void setText(String text)
7.
void setPromptText(String prompt)
8.
String getText(): returns the text in the text area.
9.
void appendText(String txt): Appends txt to the text already in the text area
10. void setEditable(boolean status)
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
javafx.application.*;
javafx.scene.Scene;
javafx.scene.control.*;
javafx.scene.layout.FlowPane;
javafx.stage.*;
public class ClickMe extends Application {
Button btn;
TextArea txtArea;
@Override
public void start(Stage stage) {
btn = new Button("CLICK ME");
btn.setOnAction(e -> btnClick());
txtArea = new TextArea();
txtArea.setPromptText("Enter text here ...");
txtArea.setPrefColumnCount(15);
txtArea.setPrefRowCount(3);
txtArea.setWrapText(true);
FlowPane pane = new FlowPane();
pane.getChildren().addAll(btn, txtArea);
Scene scene = new Scene(pane, 200, 100);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private void btnClick() {
System.out.println("TEXT ENTERED\n" + txtArea.getText());
}
}
OUTPUT
1. Run program
2. Type the 4 lines of text into the text area
3. Click button
4. Close window
COMBO BOX
1.
ComboBox<Class>() name = new ComboBox<>()
2.
ComboBox<Class> name = new ComboBox<>(ObservableList<Class> list)
Note
Creating list is as shown below:
ObservableList<Class> list = FXCollections.observableArrayList(obj, obj, …, obj);
Where “Class” represents any class in Java.
3.
ObservableList<Class> getItems(): get list of items excluding the prompt.
4.
void setItems(ObservableList<Class> items)
5.
void setEditable(boolean value)
6.
void setVisibleRowCount(int value): sets the number of items that should be visible at
the same time when the list of items is displayed.
7.
void setPromptText(String text)
8.
Class getValue(): returns the selected item and null if no item is selected.
9.
void show(): shows the list of items
10. void hide(): hides the list of items
11. boolean isShowing(): tells whether the list of items is showing.
12. SingleSelectionModel<class> getSelectionModel(): returns the selection model of the
combo box and from this object, other very important methods can be obtained:
a. void clearAndSelect(int index): it clears the previous selection sets the selection
to the selected index. Note that the index value of 0 does not correspond to the
prompt text.
b. void clearSelection(): sets selection to the prompt text.
c. void clearSelection(int index): clears the selection if the selected index matches
the argument.
d. int getSelectedIndex(): returns the index of the selected item
e. class getselectedItem(): returns the selected item.
f. string toString(): returns the selected item in string form.
g. boolean isSelected(int index): returns true if the provided index is the selected
one, and false otherwise.
h. void select(int index): sets the selected index to the argument.
i. void select(class item): sets the selected item to the argument.
j. void selectfirst()
k. void selectnext()
l. void selectlast()
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
import
javafx.application.*;
javafx.collections.*;
javafx.scene.Scene;
javafx.scene.control.*;
javafx.scene.layout.FlowPane;
javafx.stage.*;
public class ClickMe extends Application {
Button btn1, btn2, btn3;
ComboBox<String> cmb;
@Override
public void start(Stage stage) {
btn1 = new Button("SHOW/HIDE");
btn2 = new Button("GET ITEMS");
btn3 = new Button("GET SELECTED ITEM");
btn1.setOnAction(e -> btn1Click());
btn2.setOnAction(e -> btn2Click());
btn3.setOnAction(e -> btn3Click());
cmb = new ComboBox<>(FXCollections.observableArrayList(
"Sausage", "Pepperoni", "Linguica", "Salame", "Olives", "Mushrooms"
));
cmb.setPromptText("Make a choice");
cmb.setVisibleRowCount(4);
FlowPane pane = new FlowPane();
pane.getChildren().addAll(btn1, btn2, btn3, cmb);
Scene scene = new Scene(pane, 300, 200);
stage.setScene(scene);
stage.setTitle("The Click Me App");
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private void btn1Click() {
if (cmb.isShowing()) {
cmb.hide();
} else {
cmb.show();
}
}
private void btn2Click() {
String lst ="\nITEMS ON LIST\n";
ObservableList<String> items = cmb.getItems();
for(String i : items)
lst += i + "\n";
System.out.println(lst);
}
private void btn3Click() {
System.out.println("Selected item: " + cmb.getValue());
}
}
OUTPUT
1. Run program
2. Click “SHOW/HIDE”
3. Click “GET ITEMS”
4. Click “GET SELECTED ITEM”
5. Select an item
6. Click “GET SELECTED ITEM”
7. Select another item
8. Click “GET SELECTED ITEM”
9. Close window
LIST VIEW
1. ListView<Class>()
2. ListView<Class>(ObservableList<Class> items)
3. ObservableList<Class> getItems()
4. void setItems(ObervableList<Class> items)
5. void setOrientation(Orientation orien)
orien = Oritentation.HORIZONTAL or Orientation.VERTICAL
6. MultipleSelectionModel<Class>
getSelectionModel():
object
returned
provides
following important methods:
a. setSelectionMode(SelectionMode value)
value = SelectionMode.MULTIPLE, or SelectionMode.SINGLE
b. ObervableList<Class> getSelectedItems()
c. Class getSelectedItem()
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
import
javafx.application.*;
javafx.collections.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application{
Button btn;
ListView list;
@Override
public void start(Stage stage){
btn = new Button("Click me please!");
btn.setOnAction(e -> buttonClick());
list = new ListView();
list.getItems().addAll("Sausage", "Pepperoni", "Linguica", "Salame", "Olives", "Mushrooms",
"Onions", "Peppers", "Pineapple", "Spinach", "Canadian Bacon", "Tomatoes", "Kiwi", "Anchovies",
"Gummy Bears");
FlowPane pane = new FlowPane();
list.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
pane.getChildren().addAll(btn, list);
Scene scene = new Scene(pane, 300, 400);
stage.setScene(scene);
stage.setTitle("The Click Me App");
stage.show();
}
public static void main(String[] args){
Application.launch(args);
}
private void buttonClick() {
String selection = "";
ObservableList<String> sels = list.getSelectionModel().getSelectedItems();
int sn = 0;
for(String sel: sels){
the
selection += ++sn + ": " + sel + "\n";
}
// ALTERNATIVE
//for(int i = 0; i < sels.size(); i++){
//
selection += (i + 1) + ": " + sels.get(i) + "\n";
//
}
System.out.println(selection);
}
}
OUTPUT
1. Run program
2. Select “Sausage”
3. Press “Ctlr” button and select “Salame”, “Olives”, “Onions”, “Pineapple”, “Spinach”,
and “Kiwi”.
4. Click the button
5. Close the window
HORIZONTAL BOX
Places the nodes in a single row. This pane is represented by the class HBox
1.
HBox()
2.
HBox(double spacing)
3.
HBox(Node… children)
4.
HBox(double spacing, Node… children)
5.
ObservableList<Node> getChildren()
6.
static void setAlignment(Pos alignment)
7.
static void setHgrow(Node child, Priority priority): Applied to a spacer element
(preferably a node from the class Region) meant to take extra space arising from
increasing the width of the window.
8.
9.
static void setMargin(Node child, Insets margin)
-
margin = new Insets(double value) // value  margin for all 4 sides
-
margin = new Insets(double top, double right, double bottom, double left)
void setPadding(Insets space)
10. void setSpacing(double space)
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
javafx.application.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application{
Button addNode;
HBox pane = new HBox(20);
int n = 0;
@Override
public void start(Stage stage){
addNode = new Button("ADD NODE");
addNode.setOnAction(e -> buttonClick());
pane.getChildren().add(addNode);
Scene scene = new Scene(pane, 500, 50);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args){
Application.launch(args);
}
private void buttonClick() {
n++;
pane.getChildren().add(new Button("Button " + n));
}
}
OUTPUT
1. Click “ADD NODE” 5 times
2. Close window
VERTICAL BOX
Places the nodes in a single column.
1.
VBox()
2.
VBox(double spacing)
3.
VBox(Node… children)
4.
VBox(double spacing, Node… children)
5.
ObservableList<Node> getChildren()
6.
static void setAlignment(Pos alignment)
7.
static void setMargin(Node child, Insets margin)
8.
void setPadding(Insets space)
9.
void setSpacing(double space)
10. static void setVgrow(Node child, Priority priority): similar to setHgrow(…) but is
related to increase in the height of the window.
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
javafx.application.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
Button addNode;
VBox pane = new VBox(20);
int n = 0;
@Override
public void start(Stage stage) {
addNode = new Button("ADD NODE");
addNode.setOnAction(e -> buttonClick());
pane.getChildren().addAll(addNode);
Scene scene = new Scene(pane, 100, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private void buttonClick() {
n++;
pane.getChildren().add(new Button("Button " + n));
}
}
OUTPUT
1. Run program
2. Click “ADD NODE” 6 times
3. Close window
FLOW PANE
Places the nodes row-by-row horizontally or column-by-column vertically. A node is moved to
a new row or column when there is no more room.
1.
FlowPane()
2.
FlowPane(double hgap, double vgap)
-
vgap  vertical gap between rows of nodes
-
hgap  horizontal gap between columns of nodes
3.
FlowPane(double hgap, double vgap, Node… children)
4.
FlowPane(Node… children)
5.
FlowPane(Orientation
orientation):
pane
with
nodes
arranged
in
the
specified
orientation.
-
Orientation = Orientation.HORIZONTAL (default) or Orientation.VERTICAL
6.
FlowPane(Orientation orientation, double hgap, double vgap)
7.
FlowPane(Orientation orientation, double hgap, double vgap, Node... children)
8.
FlowPane(Orientation orientation, Node... children)
9.
ObservableList<Node> getChildren()
10. void setAlignment(Pos alignment): sets how nodes are aligned within the pane.
11. void setColumnAlignment(Pos alignment)
12. void setHgap(double value)
13. static void setMargin(Node child, Insets value)
14. void setOrientation(Orientation orientation)
15. void setPadding(Insets value)
16. void setRowAlignment(Pos alignment)
17. void setSpacing(double value)
18. void setVgap(double value)
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
javafx.application.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
Button addNode;
FlowPane pane = new FlowPane();
long n = 1;
@Override
public void start(Stage stage) {
addNode = new Button("ADD NODE!!!");
addNode.setOnAction(e -> buttonClick());
pane.getChildren().addAll(addNode);
Scene scene = new Scene(pane, 300, 300);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private void buttonClick() {
n = n * 10;
Button btn = new Button("Button " + n);
pane.getChildren().add(btn);
}
}
OUTPUT
1. Run program
2. Click “CLICK ME!!!” 15 times
3. Close window
TILE PANE
Similar to the flow pane. The difference is that all its nodes are positioned in cells of
the same size with the width coming from the widest node, and the height coming from the
tallest node within the pane.
1.
TilePane()
2.
TilePane(Node… children)
3.
TilePane(double hgap, double vgap)
4.
TilePane(Orientation orientation)
5.
TilePane(double hgap, double vgap, Node… children)
6.
TilePane(Orientation orientation, double hgap, double vgap)
7.
TilePane(Orientation orientation, Node… children)
8.
TilePane(Orientation orientation, double hgap, double vgap, Node… children)
9.
ObservableList<Node> getChildren()
10. void setHgap(double value)
11. void setVgap(double value)
12. void setOrientation(Orientation orientation)
13. static void setOrientation(Node node, Orientation orientation): sets the orientation
of the node within its cell.
14. void setPrefTileWidth(double value)
15. void setPrefTileHeight(double value)
16. static void setMargin(Node node, Insets value)
17. void setPadding(Insets value)
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
javafx.application.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
Button addNode;
TilePane pane = new TilePane();
long n = 1;
@Override
public void start(Stage stage) {
addNode = new Button("ADD NODE!!!");
addNode.setOnAction(e -> buttonClick());
pane.getChildren().addAll(addNode);
Scene scene = new Scene(pane, 320, 210);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private void buttonClick() {
n = n * 10;
Button btn = new Button("Button " + n);
pane.getChildren().add(btn);
}
}
OUTPUT
BORDER PANE
Places the nodes in the top, right, bottom, left, and center regions. Each region can
accommodate only one node. Important facts to note include:
➢ A region without a node is not rendered
➢ Increasing the height of the window causes heights of the left, center, and right
regions to increase.
➢ Increasing the width of the window causes the width of the top, center and bottom to
increase.
1.
BorderPane()
2.
BorderPane(Node center)
3.
BorderPane (Node center, Node top, Node right, Node bottom, Node left)
4.
void setCenter(Node node)
5.
void setTop(Node node)
6.
void setRight(Node node)
7.
void setBottom(Node node)
8.
void setLeft(Node node)
9.
void setAlignment(Pos alignment)
10. void setPadding(Insets value)
11. static void setMargin(Node child, Insets value)
Methods 4, 5, 6, 7, and 8 positions the provided nodes in the specified regions.
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
javafx.application.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
import javafx.stage.*;
public class ClickMe extends Application {
@Override
public void start(Stage stage) {
Button top = new Button("TOP REGION");
Button left = new Button("LEFT REGION");
Button bottom = new Button("BOTTOM REGION");
Button right = new Button("RIGHT REGION");
Button center = new Button("REGION REGION");
// ENSURE NODES FILL-UP THE AVAILABLE SPACE (WIDTH, AND HEIGHT)
top.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
bottom.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
center.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
left.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
right.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
BorderPane pane = new BorderPane(center, top, right, bottom, left);
pane.setPadding(new Insets(10));
Scene scene = new Scene(pane, 400, 200);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
OUTPUT
SCROLL PANE
This is a node used with panes contrary to what its name suggests. It is used with panes to
display make invisible sections of a pane -bigger than the window- visible with the aid of
scroll bars (horizontal, and vertical).
ScrollPane()
ScrollPane(Node node)
void getContent(Node node): sets the node for a scroll pane.
void setPannable(Boolean value): If true, the user can pan the contents of the scroll pane
using the mouse. The default is false.
void setPadding(Insets value)
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
javafx.application.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
Button addNode;
TilePane pane = new TilePane();
@Override
public void start(Stage stage) {
addNode = new Button("CLICK TO SHRINK PANE");
addNode.setOnAction(e -> buttonClick());
pane.getChildren().addAll(addNode);
ScrollPane scrlPane = new ScrollPane(pane);
scrlPane.setPannable(true);
Scene scene = new Scene(scrlPane, 320, 100);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private void buttonClick() {
pane.setPrefWidth(318);
}
}
OUTPUT
1. Run program
2. With cursor on window, hold down left mouse button and drag left and right
3. Click the button
4. Repeat 2
GRID PANE
Places the nodes in the cells in a grid of rows and columns. Important facts to note include:
➢ The cell for a node can be specified, and its (node smaller than its cell) alignment
within it can be specified.
➢ Nodes can be made to span multiple rows or columns
➢ Nodes smaller than their cells, can be stretch to fill their cells horizontally,
vertically, or both.
➢ Placing components on this pane requires careful planning which involves dividing the
interface into cells and noting the index of rows, and columns for each node. This
also involves noting if nodes will span rows or columns and how many will be spanned.
1.
GridPane()
2.
void add(Node node, int col, int row)
3.
void add(Node node, int col, int row, int colspan, int rowspan)
4.
void addColumn(int col, Node... nodes): adds an entire column of nodes
5.
void addRow(int row, Node... nodes): adds an entire row of columns
6.
static void setColumnSpan(Node node, int colspan)
7.
void setRowSpan(Node node, int colspan)
8.
void setHalignment(Node node, HPos value)
9.
value = HPos.LEFT, CENTER, or RIGHT
10. void setValignment(Node node, VPos value)
11. value = VPos.BOTTOM, CENTER, or TOP
12. void setHgap(double value)
13. void setVgap(double value)
14. static void setMargin(Node node, Insets value)
15. void setPadding(Insets value)
PROGRAM FOR ILLUSTRATION
Target interface below:
Columns index
0
1
2
3
4
0
Row index
1
2
import
import
import
import
import
javafx.application.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
GridPane pane = new GridPane();
@Override
public void start(Stage stage) {
pane.addRow(0, new Button("4"), new Button("5"), new Button("6"), new Button("*"), new
Button("1/x"));
pane.addRow(1, new Button("1"), new Button("2"), new Button("3"), new Button("-"));
pane.add(new Button("="), 4, 1, 1, 2);
pane.add(new Button("0"), 0, 2, 2, 1);
pane.add(new Button("."), 2, 2);
pane.add(new Button("+"), 3, 2);
Scene scene = new Scene(pane, 130, 100);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
OUTPUT
GRID PANE CONSTRAINTS
Controlling the size of row and columns require methods from two classes (ColumnConstraints
and RowConstraints).
From ColumnConstraints
1.
ColumnConstraints()
2.
ColumnConstraints(double size)
3.
ColumnConstraints(double min, double pref, double max)
4.
void setMinWidth(double value)
5.
void setMaxWidth(double value)
6.
void setPrefWidth(double value)
7.
void setPercentWidth(double value)
8.
void setHgrow(Priority value)
9.
void setHalignment(HPos value)
From RowConstraints
1.
RowConstraints()
2.
RowConstraints(double height)
3.
RowConstraints(double min, double pref, double max)
4.
void setMinHeight(double value)
5.
void setMaxHeight(double value)
6.
void setPrefHeight(double value)
7.
void setPercentHeight(double value)
8.
void setVgrow(Priority value)
9.
void setValignment(VPos value)
USING CREATED CONSTRAINTS
Doing this requires using the methods below with the constraint objects
1.
getColumnConstraints().addAll(const, const, …, const)
2.
getRowConstraints().addAll(const, const, …, const)
PROGRAM FOR ILLUSTRATION
import
import
import
import
import
import
import
javafx.application.*;
javafx.collections.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
GridPane pane = new GridPane();
@Override
public void start(Stage stage) {
pane.addRow(0, new Button("4"), new Button("5"), new Button("6"), new Button("*"),
new Button("1/x"));
pane.addRow(1, new Button("1"), new Button("2"), new Button("3"), new Button("-"));
pane.add(new
pane.add(new
pane.add(new
pane.add(new
Button("="),
Button("0"),
Button("."),
Button("+"),
4,
0,
2,
3,
1, 1, 2);
2, 2, 1);
2);
2);
// GET ALL BUTTONS AND MAKE THEM FILL AVAILABLE SPACES
ObservableList<Node> children = pane.getChildren();
for(int i = 0; i < children.size(); i++){
((Control)children.get(i)).setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
}
ColumnConstraints cc = new ColumnConstraints();
cc.setPercentWidth(20);
pane.getColumnConstraints().addAll(cc, cc, cc, cc, cc);
RowConstraints rc = new RowConstraints();
rc.setPercentHeight(100/3.0);
pane.getRowConstraints().addAll(rc, rc, rc);
pane.setHgap(10);
pane.setVgap(10);
pane.setPadding(new Insets(10));
Scene scene = new Scene(pane, 250, 150);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
OUTPUT
1. Run program
2. Close window
STACK PANE
Places the nodes on top of each other in the center of the pane.
1.
StackPane()
2.
StackPane(Node… children)
3.
ObservableList<Node> getChildren()
4.
static void setAlignment(Pos alignment)
5.
static void setMargin(Node child, Insets value)
6.
void setPadding(Insets value)
For the sake of illustrating how to use a stack pane, the following points are of importance:
-
new Rectangle(double width, double height): returns a rectangle of the specified width
and height
-
setFill(Color color):
fills the rectangle with the specified color.
A stack pane will be used to draw two rectangles stacked with the smaller on top the bigger.
PROGRAMM FOR ILLUSTRATION
import
import
import
import
import
import
javafx.application.*;
javafx.scene.*;
javafx.scene.layout.*;
javafx.scene.paint.Color;
javafx.scene.shape.*;
javafx.stage.*;
public class ClickMe extends Application {
@Override
public void start(Stage stage) {
Rectangle r1 = new Rectangle(300, 200);
r1.setFill(Color.GREEN);
Rectangle r2 = new Rectangle(100, 200);
r2.setFill(Color.WHITE);
StackPane pane = new StackPane(r1, r2);
Scene scene = new Scene(pane, 310, 210);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
OUTPUT
PROGRAMMING EXERCISES
1. Write a program to produce the interface below. Specifications that are not very
obvious are presented below:
a. Interface dimension = 460 x 461
b. Distance between buttons = 40
c. Button size = 150 x 40
d. Padding for bottom pane = 30, 40, 20, 40
e. Space between radio buttons = 10
f. Space between check boxes = 10
g. Combo box for LGA is disabled
CODE
import
import
import
import
import
import
javafx.application.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
TextField txtMat = new TextField();
TextField txtFullName = new TextField();
TextField txtMobile = new TextField();
RadioButton radMale = new RadioButton("Male");
RadioButton radFemale = new RadioButton("Female");
ComboBox cmbState = new ComboBox();
ComboBox cmbLGA = new ComboBox();
CheckBox chkWAEC = new CheckBox("WAEC");
CheckBox chkNECO = new CheckBox("NECO");
CheckBox chkNABTEB = new CheckBox("NABTEB");
Button btnSubmit = new Button("SUBMIT");
Button btnReset = new Button("RESET");
@Override
public void start(Stage stage) {
radMale.setSelected(true);
ToggleGroup tg = new ToggleGroup();
tg.getToggles().addAll(radMale, radFemale);
cmbState.setPromptText("Choose a state ...");
cmbState.setMaxWidth(Double.MAX_VALUE);
cmbLGA.setMaxWidth(Double.MAX_VALUE);
cmbLGA.setDisable(true);
HBox paneGender = new HBox(radMale, radFemale);
paneGender.setSpacing(10);
paneGender.setAlignment(Pos.CENTER_LEFT);
HBox paneResult = new HBox(chkWAEC, chkNECO, chkNABTEB);
paneResult.setAlignment(Pos.CENTER_LEFT);
paneResult.setSpacing(10);
HBox paneBottom = new HBox(40, btnSubmit, btnReset);
btnSubmit.setPrefSize(150, 40);
btnReset.setPrefSize(150, 40);
paneBottom.setPadding(new Insets(30, 40, 20, 40));
paneBottom.setAlignment(Pos.CENTER);
GridPane paneCenter = new GridPane();
paneCenter.addColumn(0, new Label("Matriculation Number: "), new Label("Full Name: "),
new Label("Mobile: "), new Label("Gender: "), new Label("State: "),
new Label("LGA: "), new Label("O'Level Result(s)- at most 2: "));
paneCenter.addColumn(1, txtMat, txtFullName, txtMobile, paneGender, cmbState, cmbLGA,
paneResult);
paneCenter.setHgap(10);
paneCenter.setVgap(10);
ColumnConstraints cc1 = new ColumnConstraints();
cc1.setPercentWidth(50);
cc1.setHalignment(HPos.RIGHT);
ColumnConstraints cc2 = new ColumnConstraints();
cc2.setPercentWidth(50); // 100/2.0
paneCenter.getColumnConstraints().addAll(cc1, cc2);
RowConstraints rc = new RowConstraints();
rc.setPercentHeight(14.28); // 100/7.0
paneCenter.getRowConstraints().addAll(rc, rc, rc, rc, rc, rc, rc);
BorderPane paneMain = new BorderPane();
paneMain.setCenter(paneCenter);
paneMain.setBottom(paneBottom);
paneMain.setPadding(new Insets(5));
Scene scene = new Scene(paneMain, 460, 461);
stage.setScene(scene);
stage.setTitle("SUBMIT STUDENT DETAILS");
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
2.
Write a program to produce the interface below, with the provided specifications:
a. Horizontal and vertical gap separating all components is 10px.
b. The grid has a padding of 10px all round.
c. Text filed for phone number has a maximum width of 200px.
d. Both buttons have a minimum width of 80px.
e. Stage has a minimum width of 500px and a maximum width of 600px.
CODE
import
import
import
import
import
import
javafx.application.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
TextField txtName, txtPhone, txtAddress;
RadioButton rdoSmall, rdoMedium, rdoLarge, rdoThin, rdoThick;
CheckBox chkPepperoni, chkMushrooms, chkAnchovies;
@Override
public void start(Stage stage) {
txtName = new TextField(); txtPhone = new TextField(); txtAddress = new TextField();
rdoSmall = new
rdoLarge = new
rdoThick = new
chkPepperoni =
chkAnchovies =
RadioButton("Small"); rdoMedium = new RadioButton("Medium");
RadioButton("Large"); rdoThin = new RadioButton("Thin");
RadioButton("Thick");
new CheckBox("Pepperoni"); chkMushrooms = new CheckBox("Mushrooms");
new CheckBox("Anchovies");
txtName.setPromptText("Enter the name here");
txtPhone.setPromptText("Enter the phone number here");
txtPhone.setMaxWidth(200);
txtAddress.setPromptText("Enter the address here");
rdoMedium.setSelected(true); rdoThin.setSelected(true);
ToggleGroup groupSize = new ToggleGroup();
groupSize.getToggles().addAll(rdoSmall, rdoMedium, rdoLarge);
ToggleGroup groupCrust = new ToggleGroup();
groupCrust.getToggles().addAll(rdoThin, rdoThick);
Button btnOK = new Button("OK"), btnCancel = new Button("Cancel");
btnOK.setMinWidth(80); btnCancel.setMinWidth(80);
VBox paneSize = new VBox(10, new Label("Size"), rdoSmall, rdoMedium, rdoLarge);
VBox paneCrust = new VBox(10, new Label("Crust"), rdoThin, rdoThick);
VBox paneToppings = new VBox(10, new Label("Topping"), chkPepperoni, chkMushrooms,
chkAnchovies);
HBox paneButtons = new HBox(10, btnOK, btnCancel);
GridPane grid = new GridPane();
grid.setPadding(new Insets(10));
grid.setHgap(10);
grid.setVgap(10);
grid.addRow(0, new Label("Name: "), txtName);
grid.addRow(1, new Label("Phone number: "), txtPhone);
grid.addRow(2, new Label("Address: "), txtAddress);
grid.addRow(3, paneSize, paneCrust, paneToppings);
grid.add(paneButtons, 2, 4);
GridPane.setColumnSpan(txtName, 2);
GridPane.setColumnSpan(txtPhone, 2);
GridPane.setColumnSpan(txtAddress, 2);
ColumnConstraints c1 = new ColumnConstraints();
c1.setPercentWidth(33);
c1.setHalignment(HPos.RIGHT);
ColumnConstraints c2 = new ColumnConstraints();
c2.setPercentWidth(33);
grid.getColumnConstraints().addAll(c1, c2, c2);
Scene scene = new Scene(grid);
stage.setScene(scene);
stage.setMinWidth(500);
stage.setMaxWidth(600);
stage.setTitle("Pizza Order");
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
}
3.
Write a program that switches the panes at a center in response to a button clicked.
The interface specifications are as show below:
a. The interface is 250 x 200.
b. Buttons are separated by 10px.
c. The pane with the buttons has a right margin of 10px.
d. Write separate functions to handle the expected switching for each button clicked.
CODE
import
import
import
import
import
import
javafx.application.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class ClickMe extends Application {
VBox pane1;
VBox pane2;
VBox pane3;
StackPane paneStack;
@Override
public void start(Stage stage) {
pane1 = new VBox(new Label("PANE 1 IN THE STACK"));
pane2 = new VBox(new Label("PANE 2 IN THE STACK"));
pane3 = new VBox(new Label("PANE 3 IN THE STACK"));
paneStack = new StackPane(pane1);
Button btn1 = new Button("SHOW PANE 1");
Button btn2 = new Button("SHOW PANE 2");
Button btn3 = new Button("SHOW PANE 3");
btn1.setOnAction(e -> btn1Click());
btn2.setOnAction(e -> btn2Click());
btn3.setOnAction(e -> btn3Click());
VBox paneButtons = new VBox(10, btn1, btn2, btn3);
BorderPane paneBorder = new BorderPane();
paneBorder.setLeft(paneButtons);
paneBorder.setCenter(paneStack);
paneBorder.setPadding(new Insets(10));
BorderPane.setMargin(paneButtons, new Insets(0, 10, 0, 0));
Scene scene = new Scene(paneBorder, 250, 200);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
Application.launch(args);
}
private void btn1Click(){
paneStack.getChildren().clear();
paneStack.getChildren().add(pane1);
}
private void btn2Click(){
paneStack.getChildren().clear();
paneStack.getChildren().add(pane2);
}
private void btn3Click(){
paneStack.getChildren().clear();
paneStack.getChildren().add(pane3);
}
}
EVENT-DRIVEN PROGRAMMING
EVENT: an object generated (automatically) when a user does something noteworthy with one
of the components constituting a user interface. Event objects are represented by the class
javafx.event.Event and its subclasses (listed below).
The table below shows some classes of events and the actions of a user that can generate
them.
Event Class
User’s Action
ActionEvent
-
Click a button
-
Press Enter in a text input field
-
Check or uncheck radio button
-
Check or uncheck a check box
-
Select a new item from a combo box
-
Mouse pressed
-
Mouse released
-
Mouse clicked
-
Mouse entered
-
Mouse exited
-
Mouse moved
-
Mouse dragged
-
Key pressed
-
Key released
-
Key typed
-
Open a window
MouseEvent
KeyEvent
WindowEvent
-
Close a window
SOURCE: the component interacted with on the user interface.
LISTENER/HANDLER: an object of the handler interface (javafx.event.EventHandler) in which
is provided statements that must be executed in response to the event. These statements are
provided in the abstract method handle(…). This method takes the event object generated as
its argument i.e. handle(EventClass event) where EventClass represents the class Event or
any of its subclasses.
The main things done in event-driven programming are:
1. Create an event source (done when building the stage).
2. Create an event handler or listener.
3. Register the event handler with the event source (link source and handler)
CREATING AN EVENT HANDLER
1. Using the Application
The
Application
representing
the
stage
(frame/window)
is
made
to
implement
the
EventHandler and as a result the abstract method handle(…) is implemented within it.
// IMPORT NECESSARY PACKAGES
public class Experiments extends Application implements EventHandler {
:
:
@Override
public void handle(Event t) {
// execute when event occurs
}
}
2. Use an Inner Class
Use an inner class defined (usually private) within Application to implement EventHandler.
// IMPORT NECESSARY PACKAGES
public class Experiments extends Application {
@Override
public void start(Stage stage) {
:
:
}
public static void main(String[] args) {
Application.launch(args);
}
private class HandlerClass implements EventHandler{
@Override
public void handle(Event e) {
// execute when event occurs
}
}
}
3. Use an Anonymous Inner Class
Unassigned constructor + method body/implementation  Anonymous class  EventHandler.
The anonymous class is defined within the Application.
new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent t) {
// execute when event occurs
}
}
4. Using Lambda Expression
This approach is derived from 3 (using anonymous inner class). In this case, the name of
the interface and the abstract method to implement are replaced by a variable name and
the arrow operator. This is because EventHandler interface is said to be a functional
interface because it has only one abstract method.
e -> {
// execute when event occurs
}
It is important to note that, the body of the method in the above syntax can be replaced
with a call to a method that has already been implemented. This is as shown below:
e -> executeMethod(...)
LINKING EVENT HANDLER AND EVENT SOURCE
Doing this requires invoking/calling a method (I will like to call it the linking method)
through the event source and supplying the instance of the listener as argument to the
invoked method. The name of the method invoked and class of the handler depend on the type
of event. Some of these methods are listed below:
1.
setOnAction(EventHandler<ActionEvent>)
2.
setOnMousePressed(EventHandler<MouseEvent>)
3.
setOnMouseReleased(EventHandler<MouseEvent>)
4.
setOnMouseClicked(EventHandler<MouseEvent>)
5.
setOnMouseEntered(EventHandler<MouseEvent>)
6.
setOnMouseExited(EventHandler<MouseEvent>)
7.
setOnMouseMoved(EventHandler<MouseEvent>)
8.
setOnMouseDragged(EventHandler<MouseEvent>)
9.
setOnKeyPressed(EventHandler<KeyEvent>)
10. setOnKeyReleased(EventHandler<KeyEvent>)
11. setOnKeyTyped(EventHandler<KeyEvent>)
Registration is done using the format below:
sourceObject.linkingMethod(handlerObject);
The object of the event handler can be made available through:
a. an instance of the Application
b. an instance of the inner class within Application
c. an anonymous inner class
d. an anonymous inner class in lambda expression
e. an anonymous inner class in lambda expression with a helper method
Linking in cases (c), (d), and (e) above are done directly with the event source of interest.
This ensures that the handler object can only be linked with the source of interest.
Examples will now be presented using each of the above approaches for the handlerObject.
The program below uses the 3 sides of a triangle to compute and display its area.
(a)
CODE WITH APPLICATION AS HANDLER
import
import
import
import
import
import
import
javafx.application.*;
javafx.event.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class EventIssues extends Application implements EventHandler {
TextField txtA, txtB, txtC, txtAns;
Button btnSolve;
@Override
public void start(Stage stage) throws Exception {
txtA = new TextField();
txtB = new TextField();
txtC = new TextField();
txtAns = new TextField();
txtAns.setEditable(false);
btnSolve = new Button("SOLVE");
btnSolve.setPrefSize(230, 150);
GridPane paneGrid = new GridPane();
paneGrid.addColumn(0, new Label("Side A: "), new Label("Side B: "), new Label("Side C: "), new
Label("Answer: "));
paneGrid.addColumn(1, txtA, txtB, txtC, txtAns);
paneGrid.add(btnSolve, 0, 4);
GridPane.setColumnSpan(btnSolve, 2);
paneGrid.setHgap(10);
paneGrid.setVgap(10);
paneGrid.setPadding(new Insets(10));
Scene scene = new Scene(paneGrid, 230, 200);
stage.setScene(scene);
stage.setTitle("TRIANGLE");
stage.show();
// LINK EVENT SOURCE WITH HANDLER (EventIssues ==> Application class)
btnSolve.setOnAction(this);
}
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void handle(Event t) {
// Get entered sides and convert them to numbers
double a, b, c;
a = Double.parseDouble(txtA.getText());
b = Double.parseDouble(txtB.getText());
c = Double.parseDouble(txtC.getText());
// Calculate area
double s = (a + b + c) / 2;
double area = Math.sqrt(s * (s - a) * (s - b) * (s - c));
// Print area on interface as a String
txtAns.setText(area + "");
}
}
(b) CODE WITH OBJECT OF INNER CLASS AS HANDLER
import
import
import
import
import
import
import
javafx.application.*;
javafx.event.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class EventIssues extends Application {
TextField txtA, txtB, txtC, txtAns;
Button btnSolve;
@Override
public void start(Stage stage) throws Exception {
txtA = new TextField();
txtB = new TextField();
txtC = new TextField();
txtAns = new TextField();
txtAns.setEditable(false);
btnSolve = new Button("SOLVE");
btnSolve.setPrefSize(230, 150);
GridPane paneGrid = new GridPane();
paneGrid.addColumn(0, new Label("Side A: "), new Label("Side B: "), new Label("Side C: "), new
Label("Answer: "));
paneGrid.addColumn(1, txtA, txtB, txtC, txtAns);
paneGrid.add(btnSolve, 0, 4);
GridPane.setColumnSpan(btnSolve, 2);
paneGrid.setHgap(10);
paneGrid.setVgap(10);
paneGrid.setPadding(new Insets(10));
Scene scene = new Scene(paneGrid, 230, 200);
stage.setScene(scene);
stage.setTitle("TRIANGLE");
stage.show();
// LINK EVENT SOURCE WITH HANDLER (Handler class below)
btnSolve.setOnAction(new Handler());
}
public static void main(String[] args) {
Application.launch(args);
}
// PRIVATE INNER CLASS IMPLEMENTING EVENTHANDLER
private class Handler implements EventHandler {
@Override
public void handle(Event t) {
// Get entered sides and convert them to numbers
double a, b, c;
a = Double.parseDouble(txtA.getText());
b = Double.parseDouble(txtB.getText());
c = Double.parseDouble(txtC.getText());
// Calculate area
double s = (a + b + c) / 2;
double area = Math.sqrt(s * (s - a) * (s - b) * (s - c));
// Print area on interface as a String
txtAns.setText(area + "");
}
}
}
(c) CODE WITH OBJECT OF AN ANONYMOUS INNER CLASS AS HANDLER
import
import
import
import
import
import
import
javafx.application.*;
javafx.event.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class EventIssues extends Application {
TextField txtA, txtB, txtC, txtAns;
Button btnSolve;
@Override
public void start(Stage stage) throws Exception {
txtA = new TextField();
txtB = new TextField();
txtC = new TextField();
txtAns = new TextField();
txtAns.setEditable(false);
btnSolve = new Button("SOLVE");
btnSolve.setPrefSize(230, 150);
GridPane paneGrid = new GridPane();
paneGrid.addColumn(0, new Label("Side A: "), new Label("Side B: "), new Label("Side C: "), new
Label("Answer: "));
paneGrid.addColumn(1, txtA, txtB, txtC, txtAns);
paneGrid.add(btnSolve, 0, 4);
GridPane.setColumnSpan(btnSolve, 2);
paneGrid.setHgap(10);
paneGrid.setVgap(10);
paneGrid.setPadding(new Insets(10));
Scene scene = new Scene(paneGrid, 230, 200);
stage.setScene(scene);
stage.setTitle("TRIANGLE");
stage.show();
// LINK EVENT SOURCE WITH HANDLER (Anonymous inner class)
btnSolve.setOnAction(new EventHandler() {
@Override
public void handle(Event t) {
// Get entered sides and convert them to numbers
double a, b, c;
a = Double.parseDouble(txtA.getText());
b = Double.parseDouble(txtB.getText());
c = Double.parseDouble(txtC.getText());
// Calculate area
double s = (a + b + c) / 2;
double area = Math.sqrt(s * (s - a) * (s - b) * (s - c));
// Print area on interface as a String
txtAns.setText(area + "");
}
});
}
public static void main(String[] args) {
Application.launch(args);
}
}
(d) CODE WITH HANDLER OBJECT AS LAMBDA EXPRESSION
import
import
import
import
import
import
javafx.application.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class EventIssues extends Application {
TextField txtA, txtB, txtC, txtAns;
Button btnSolve;
@Override
public void start(Stage stage) throws Exception {
txtA = new TextField();
txtB = new TextField();
txtC = new TextField();
txtAns = new TextField();
txtAns.setEditable(false);
btnSolve = new Button("SOLVE");
btnSolve.setPrefSize(230, 150);
GridPane paneGrid = new GridPane();
paneGrid.addColumn(0, new Label("Side A: "), new Label("Side B: "), new Label("Side C: "), new
Label("Answer: "));
paneGrid.addColumn(1, txtA, txtB, txtC, txtAns);
paneGrid.add(btnSolve, 0, 4);
GridPane.setColumnSpan(btnSolve, 2);
paneGrid.setHgap(10);
paneGrid.setVgap(10);
paneGrid.setPadding(new Insets(10));
Scene scene = new Scene(paneGrid, 230, 200);
stage.setScene(scene);
stage.setTitle("TRIANGLE");
stage.show();
// LINK EVENT SOURCE WITH HANDLER (Anonymous inner class)
btnSolve.setOnAction( t -> {
double a, b, c;
a = Double.parseDouble(txtA.getText());
b = Double.parseDouble(txtB.getText());
c = Double.parseDouble(txtC.getText());
// Calculate area
double s = (a + b + c) / 2;
double area = Math.sqrt(s * (s - a) * (s - b) * (s - c));
// Print area on interface as a String
txtAns.setText(area + "");
});
}
public static void main(String[] args) {
Application.launch(args);
}
}
(e) CODE WITH HANDLER OBJECT AS LAMBDA EXPRESSION TIED TO A HELPER METHOD
import
import
import
import
import
import
javafx.application.*;
javafx.geometry.*;
javafx.scene.*;
javafx.scene.control.*;
javafx.scene.layout.*;
javafx.stage.*;
public class EventIssues extends Application {
TextField txtA, txtB, txtC, txtAns;
Button btnSolve;
@Override
public void start(Stage stage) throws Exception {
txtA = new TextField();
txtB = new TextField();
txtC = new TextField();
txtAns = new TextField();
txtAns.setEditable(false);
btnSolve = new Button("SOLVE");
btnSolve.setPrefSize(230, 150);
GridPane paneGrid = new GridPane();
paneGrid.addColumn(0, new Label("Side A: "), new Label("Side B: "), new Label("Side C: "), new
Label("Answer: "));
paneGrid.addColumn(1, txtA, txtB, txtC, txtAns);
paneGrid.add(btnSolve, 0, 4);
GridPane.setColumnSpan(btnSolve, 2);
paneGrid.setHgap(10);
paneGrid.setVgap(10);
paneGrid.setPadding(new Insets(10));
Scene scene = new Scene(paneGrid, 230, 200);
stage.setScene(scene);
stage.setTitle("TRIANGLE");
stage.show();
// LINK EVENT SOURCE WITH HANDLER (Lambda expression with helper method)
btnSolve.setOnAction(t -> computeArea());
}
public static void main(String[] args) {
Application.launch(args);
}
private void computeArea() {
double a, b, c;
a = Double.parseDouble(txtA.getText());
b = Double.parseDouble(txtB.getText());
c = Double.parseDouble(txtC.getText());
// Calculate area
double s = (a + b + c) / 2;
double area = Math.sqrt(s * (s - a) * (s - b) * (s - c));
// Print area on interface as a String
txtAns.setText(area + "");
}
}
OUTPUT FROM EACH PROGRAM ABOVE
FORMATTING WITH CSS
SELECTORS
Selector  .styleClassName or #idValue (for a unique component)
JavaFX has default style class names derived from the class name. This is done by writing
the class names in lower case and using hyphen (-) between words, if the class name has
more than one word e.g. CheckBox  check-box, RadioButton  radio-button, Button  button
etc.
Some subclasses of the Node class don’t have default style class names. For example, layout
panes such as HBox, VBox etc. as well as shapes such as Rectangle, Circle etc. Style class
names have to be created for classes of this sort. Syntax is given below
guiComponent.getStyleClass().add(“created_style_class_name”).
STYLE RULE SYNTAX
Style sheet contains one or more style rules. Syntax for a style rule is as shown below:
Selector{
property: value;
property: value;
:
property: value;
}
Style rules can be administered through:
1. Inline (directly on the GUI component)
guiComponent.setStyle(“property: value”);
2. External style sheet in same directory as .class file (preferably on a scene)
scene.getStyleSheets().add(“sheetName.css”);
3. External style sheet in another directory
scene.getStylesheets().add(getClass().getResource(“sheetName.css”).toExternalForm());
STYLE PROPERTIES
Properties used in the style rule are majorly CSS properties preceded by -fx-. For example,
background-color  -fx-background-color, font  -fx-font. Below are some important style
properties:
1.
-fx-font-family: serif, sans-serif, cursive, fantasy, or monospace
2.
-fx-font-size: number ending in pt (point) or px (pixel)
3.
-fx-font-style: normal, italic, or oblique
4.
-fx-font-weight: normal, bold, bolder, lighter, 100, 200, 300, 400, 500,…,800, or 900
5.
-fx-font: (combination of one or more of the above values)
6.
-fx-background-color: color name (e.g. cornsilk, thistle, papayawhip, aliceblue, red,
blue, green etc.), #RRGGBB (e.g. #f5f5f5)
7.
-fx-border-width: number in pixels
8.
-fx-border-style: none, solid, dotted, or dashed
9.
-fx-border-color
Program for Illustration
Java File
import javafx.application.*;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class Experiment extends Application {
Button btn;
Label fontLbl;
int n;
@Override
public void start(Stage stage) {
n = 0;
String[] typeface = {"serif", "sans-serif", "cursive", "fantasy", "monospace"};
fontLbl = new Label(typeface[n].toUpperCase());
fontLbl.setStyle("-fx-font: 20px " + typeface[n] + ";");
btn = new Button("SWITCH FONTS");
VBox pane = new VBox(10, btn, fontLbl);
pane.setPadding(new Insets(10));
// CREATE A STYLE CLASS FOR THE PANE WHICH HAS NONE
pane.getStyleClass().add("pane");
// GIVE THE LABEL AN ID
fontLbl.setId("label");
Scene scene = new Scene(pane, 200, 100);
// LINK SCENE TO EXTERNAL STYLE SHEET
scene.getStylesheets().add(getClass().getResource("CSS.css").toExternalForm());
stage.setScene(scene);
stage.show();
btn.setOnAction(e -> {
n++;
if (n == 5) {
n = 0;
}
fontLbl.setText(typeface[n].toUpperCase());
fontLbl.setStyle("-fx-font: 20px " + typeface[n] + ";");
});
}
public static void main(String[] args) {
Application.launch(args);
}
}
CSS File
.pane{
-fx-background-color:cornsilk;
}
.pane, .button, .label{
-fx-border-style: solid;
-fx-border-width: 2px;
}
.button{
-fx-background-color: yellow;
-fx-font-weight: bolder;
}
OUTPUT (Click button “SWITCH FONTS” 5 times)
EXCEPTION HANDLING
The occurrence of an exception (error) will prevent further execution of a program.
Preventing this requires dealing with it. One way of doing this is by using a try-catch
block of codes. Statements after the one that generated the exception are not executed.
Try-catch syntax is given below:
try{
Statement(s) likely to generate exception stay here
}
catch(ExceptionClass var){
Statement(s) executed when the exception occurs
}
finally{
Represents statement(s) executed whether or not exception occurs, if the block is
present
}
EXCEPTION UNHANDLED
public class Experiment2 {
public static void main(String[] args) {
int a = Integer.parseInt("6");
System.out.println("a = " + a);
int b = Integer.parseInt("b");
System.out.println("b = " + b);
System.out.println("END");
}
}
SAMPLE OUTPUT
a = 6
Exception in thread "main" java.lang.NumberFormatException: For input string: "b"
EXCEPTION HANDLED
public class Experiment2 {
public static void main(String[] args) {
try {
int a = Integer.parseInt("6");
System.out.println("a = " + a);
int b = Integer.parseInt("b");
System.out.println("b = " + b);
System.out.println("END");
} catch (Exception err) {
System.out.println("\nERROR!!1 String is not a numeric.");
}
}
}
SAMPLE OUTPUT
a = 6
ERROR!!1 String is not a numeric.
EXCEPTION HANDLED WITH FINAL BLOCK
public class Experiment2 {
public static void main(String[] args) {
try {
int a = Integer.parseInt("6");
System.out.println("a = " + a);
int b = Integer.parseInt("b");
System.out.println("b = " + b);
} catch (Exception err) {
System.out.println("\nERROR!!1 String is not a numeric.");
} finally {
System.out.println("END");
}
}
}
SAMPLE OUTPUT
a = 6
ERROR!!1 String is not a numeric.
END
FILE PROCESSING
File names are either absolute (when they start with a drive letter) or relative (when they
don’t). When giving slashes in file paths it is either \\ (for windows) or / (all OS).
1.
File(pathname: String) – creates a File object for a file or directory. For example:
a. new File(“c:\\book”) or new File(“c:/book”)  Directory
b. new File(“c:\\book\\test.dat”) or new File(“c:/book/test.dat”)
2.
File(parent: String, child: String) – creates a File object for a subdirectory/file in
the parent directory
3.
File(parent: File, child: String) – similar to (2) except that the parent is represented
by a file object.
4.
createNewFile(): boolean – creates the associated file (all directories in the path
must have been created) and returns true if the file wasn’t existing and false it
already exist.
5.
exists(): boolean – returns true if the file or directory represented by the file object
exists.
6.
canRead(): boolean – returns true if the associated file can be read i.e. data can be
obtained from it.
7.
canWrite(): boolean – returns true if associated file can be written to.
8.
isDirectory(): boolean – returns true if file object represents a directory.
9.
isFile(): boolean – returns true if file object represents a file.
10. isAbsolute(): boolean – returns true if the file object was created with an absolute
path.
11. isHidden(): boolean – returns true if the file or directory is hidden.
12. getAbsolutePath(): String – returns the absolute path of a directory or file.
13. getName(): String – returns the last name and extension of the associated file.
14. getPath(): String – returns the complete directory and file name of the file object.
15. getParent(): String – gets a string of all directories above the associated directory
or file. null is returned if there is no directory in the name used for creating the
file object.
16. lastModified(): long – returns the time (timestamp) that the file was last modified.
17. length(): long – returns the size of the file or 0 if it doesn’t exist or is a directory.
18. listFile(): File[] – returns an array of file objects representing the files contained
in the directory represented by the file object.
19. delete(): boolean – deletes the associated file or directory and returns true if
successful.
20. renameTo(dest: File): boolean – renames the associated file or directory to the name
of the File object provided as argument, returning true if successful.
21. mkdir(): boolean – creates the last directory in a file name if it is not existing and
returns true if the process is successful. It is important to ensure the file name has
only directories and only the last is non-existent in the system.
22. mkdirs(): boolean – creates all non-existent directories in a file name. The file name
has to have only directory names.
PROCESSING TEXT FILES
WRITING WITH PRINTWRITER
1.
PrintWriter(file: File): file is linked to the file to be processed.
2.
PrintWriter(filename: String)
-
The file is created if it wasn’t existing before construction, and overwritten if it
was.
Methods to use through the PrintWriter object include:
3.
print(data)
4.
println(data)
5.
printf(data)
6.
close(): must be invoked after the write operation has been completed otherwise the
file will end up corrupted.
data  String, char, char[], int, long, float, double, or Boolean
CODE
import java.io.*;
public class Experiment3 {
public static void main(String[] args){
try{
File f = new File("Text File.txt");
PrintWriter pw = new PrintWriter(f);
pw.println(5);
pw.println(234l);
pw.println(2.4e-5);
pw.println(2.5f);
pw.println(true);
pw.println('#');
pw.println("String");
char[] charArray = {'c','h','a','r',' ','a','r','r','a','y'};
pw.println(charArray);
pw.close();
}
catch(Exception err){
System.out.println("Error opening file.");
}
}
}
FILE CONTENT
READING FROM FILE WITH SCANNER
1.
Scanner(file: File): creates a Scanner object using the File object created using a
text file.
2.
hasNext(): boolean – returns true if there is still data (String) to read from the
file. There are similar methods for other data types in Java e.g. hasNextLine()
3.
useDelimiter(pattern: String): Scanner – changes the default delimiter (white space)
to the pattern.
4.
close(): void – close the file after reading to prevent corruption.
Note:
- The file to be read from must be available to prevent the FileNotFoundException.
-
The methods already known for reading through Scanner from the keyboard, are the ones
used when reading from file.
CODE READING FROM EARLIER FILE
import java.io.*;
import java.util.*;
public class Experiment3 {
public static void main(String[] args){
try{
File file = new File("Text File.txt");
Scanner sourceFile = new Scanner(file);
while(sourceFile.hasNext())
System.out.println(sourceFile.next());
sourceFile.close();
}
catch(Exception err){
System.out.println("Error opening file.");
}
}
}
OUTPUT
5
234
2.4E-5
2.5
true
#
String
char
array
When \n is used as delimiter i.e.
sourceFile.useDelimiter("\n");
the output will be as given below (pay attention to char array)
5
234
2.4E-5
2.5
true
#
String
char array
READING FROM FILE WITH FILEREADER
1. FileReader(file: File)
2. FileReader(filename: String)
3. read(): int – reads and returns the code of a character from the opened file. It returns
-1 (EOF  End of File code) when there is no character left to read.
4. readLine
5. close(): void – close the opened file at the end of reading.
CODE
package javafxexample1;
import java.io.*;
public class Experiment3 {
public static void main(String[] args){
try{
File file = new File("Text File.txt");
FileReader sourceFile = new FileReader(file);
// read first character code
int c = sourceFile.read();
while(c != -1){
System.out.print((char)c);
c = sourceFile.read();
}
sourceFile.close();
}
catch(Exception err){
System.out.println("Error opening file.");
}
}
}
OUTPUT
5
234
2.4E-5
2.5
true
#
String
char array
PROCESSING BINARY FILES
WRITING WITH FileOutputStream
This class is a subclass of the abstract class OutputStream and it is that supplies the
additional methods listed.
1.
FileOutputStream(file: File)
2.
FileOutputStream(fileURL: String)
3.
FileOutputStream(file: File, append: boolean)
4.
FileOutputStream(fileURL: String, append: boolean)
Note:
a. 1 and 2 will create and open a new file (that overwrites a previously existing one
if available)
b. 3 and 4 will create and open a new file if it wasn’t existing, and just open a
previously existing one for appending new bytes of data.
5.
write(data: int)
6.
close(): void – closes the stream
CODE
package javafxexample1;
import java.io.*;
public class Experiment3 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("Test.txt");
for(int i = 'A'; i <= 'Z'; i++)
fos.write(i);
fos.write('\n');
fos.close();
} catch (Exception err) {
}
}
}
STATE OF FOLDER BEFORE EXECUTION
STATE OF FOLDER AFTER EXECUTION
Test.txt OPENED
CODE TO APPEND CONTENT TO AN EXISTING FILE
package javafxexample1;
import java.io.*;
public class Experiment3 {
public static void main(String[] args) {
try {
FileOutputStream fos = new FileOutputStream("Test.txt", true);
for(int i = 'a'; i <= 'z'; i++)
fos.write(i);
fos.write('\n');
fos.close();
} catch (Exception err) {
}
}
}
Test.txt OPENED
READING WITH FileInputStream
This class is a subclass of the abstract class InputStream and it is that supplies the
additional methods listed.
1.
FileInputStream(file: File)
2.
FileInputStream(fileURL: String)
3.
read(): int – returns the next byte of data to be read and -1 if there is nothing left.
4.
available(): int – returns the number of bytes of data available for reading.
5.
close(): void – closes the stream
CODE TO READE THE CONTENT OF Test.txt
package javafxexample1;
import java.io.*;
public class Experiment3 {
public static void main(String[] args) {
try {
FileInputStream fis = new FileInputStream("Test.txt");
System.out.println("Available data = " + fis.available());
System.out.println("\nCONTENT OF Test.txt");
int d = fis.read();
while(d != -1){
System.out.print((char)d);
d = fis.read();
}
} catch (Exception err) {
}
}
}
OUTPUT
WRITING WITH DataOutputStream
The class is a subclass of OutputStream and implements DataOutput which provides methods to
write various types of data.
1.
DataOutputStream(outStream: OutputStream) – the argument can also be an instance of
FileOutputStream
2.
writeBoolean(data: boolean): void
3.
writeByte(data: int): void – writes the 8 lower bits of data (16 bits) to the stream
i.e. the first 8 bits of v. For example, 259, will be written as 3 to the stream.
4.
writeBytes(s: String): void – writes the lower byte of the characters in a String to
the stream. This implies a character that is represented by more than 1 byte, will be
written to the stream as a different character. For example, under normal circumstance
(char)359 = ŧ, if written to the stream becomes g.
5.
writeChar(c: char): void – writes a character (2 bytes) to the stream
6.
writeChars(s: String) – writes every character in s to the stream
7.
writeFloat(v: float): void
8.
writeDouble(v: double): void
9.
writeInt(v: int): void
10. writeLong(v: long): void
11. writeShort(v: short): void
12. writeUTF(s: String): void - The UTF format uses different number of bits to code the
characters in a string, unlike what obtains in ASCII and Unicode – 8bits if code <=
0x7F, 16bits if code > 0x7F but <= 0x7FF, and 24bits if code > 0x7FF.
READING WITH DataInputStream
This class is a subclass of InputStream and implements the interface, DataInput, which
provides methods to read (get) native data types (not just integers).
1.
DataInputStream(in: InputStream) – InputStream can be replaced with FileInputStream,
as argument.
2.
readBoolean(): Boolean
3.
readByte(): byte
4.
readChar(): char
5.
readFloat(): float
6.
readDouble(): double
7.
readInt(): int
8.
readLong(): long
9.
readShort(): short
10. readLine(): String
11. readUTF(): String
When reading multiple data form a binary file the end of the file is indicated by the
generation of an EOFExcepton. If all data in a file are to be read using the methods in
this class, then the loop that should be used is one with a condition that is always true,
and will only stop when the EOFException has been generated.
USING FILE CHOOSER DIALOG
Using a file dialog window provides a means of choosing the file that will be processed.
Using a file chooser requires:
1.
FileChooser() - creates a FileChooser object which represents a file chooser dialog.
2.
setTitle(title: String): void – sets the title of the dialog
3.
showOpenDialog(window: Window): File – shows the dialog to allow the choosing of a file,
with window  stage or null. Clicking the Open-button after selecting a file, closes
the dialog and return a file object representing the file selected for opening, while
clicking the Cancel-button will return a null.
4.
FileChooser.ExensionFilter(description:
String,
sample:
String)
–
used
to
provide
options in a combo box in the dialog on the type of file to be chosen.
5.
getExtensionFilters(): ObservableList<ExtensionFilter> - returns among other things a
means of adding extension filters to the dialog to enable the choosing of certain file
types.
Download