JavaFX Basics
IA Preparation: JavaFX is not part of the assessed IB CS syllabus, but it is the standard toolkit for building GUI applications in Java – essential for most IA projects.
Table of Contents
- Why This Page Exists
- Key Concepts
- Common Controls
- Layout Containers
- Event Handling
- Alerts and Dialogs
- Putting It Together
- Common Patterns for IA Projects
- Quick Check
- Code Completion
- Spot the Error
- Predict the Output
- Practice Exercises
- Connections
Why This Page Exists
Your IB Internal Assessment requires a working application that solves a real problem for a real client. Most IA projects need a graphical user interface (GUI) so the client can interact with the program without using a terminal.
JavaFX is Java’s built-in GUI framework. This page covers the minimum you need to start building functional interfaces – windows, buttons, text fields, and event handling. Later pages cover MVC architecture, FXML and controllers, and file persistence.
Goal: By the end of this page, you should be able to create a window with controls that respond to user interaction.
Key Concepts
The JavaFX Architecture
Every JavaFX application has three layers:
| Layer | Class | Analogy |
|---|---|---|
| Stage | Stage | The window frame |
| Scene | Scene | The canvas inside the frame |
| Nodes | Button, Label, TextField, etc. | The UI elements drawn on the canvas |
A Stage contains one Scene, and a Scene contains a tree of nodes (controls and layout containers). You can swap scenes on a stage to show different screens.
Application Lifecycle
Every JavaFX app extends Application and overrides the start method:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class HelloApp extends Application {
@Override
public void start(Stage stage) {
Label greeting = new Label("Hello, JavaFX!");
StackPane root = new StackPane(greeting);
Scene scene = new Scene(root, 400, 300);
stage.setTitle("My First App");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
What happens when this runs:
launch()creates theApplicationand callsstart()start()receives the primaryStage(window)- We create controls, put them in a layout, wrap the layout in a
Scene - We set the scene on the stage and call
show()
You never call start() yourself – launch() does it for you.
Common Controls
Label
Displays read-only text. Use labels for headings, instructions, or showing results.
Label title = new Label("Student Manager");
Label result = new Label(""); // empty -- updated later
result.setText("Found 3 students"); // update the text
TextField
A single-line text input. Use getText() to read what the user typed, and clear() to reset it.
TextField nameField = new TextField();
nameField.setPromptText("Enter student name"); // placeholder text
String name = nameField.getText(); // read the input
nameField.clear(); // clear after use
Button
A clickable button. Attach behaviour using setOnAction().
Button addBtn = new Button("Add Student");
addBtn.setOnAction(event -> {
String name = nameField.getText();
result.setText("Added: " + name);
nameField.clear();
});
TextArea
A multi-line text area for longer input or output display.
TextArea outputArea = new TextArea();
outputArea.setEditable(false); // read-only display
outputArea.setPrefRowCount(10);
outputArea.appendText("Line 1\n");
outputArea.appendText("Line 2\n");
ComboBox
A dropdown selector for choosing from a list of options.
ComboBox<String> gradeBox = new ComboBox<>();
gradeBox.getItems().addAll("Grade 11", "Grade 12");
gradeBox.setValue("Grade 11"); // default selection
String selected = gradeBox.getValue(); // read selection
CheckBox
A toggle for boolean options.
CheckBox hlBox = new CheckBox("HL Student");
boolean isHL = hlBox.isSelected(); // true or false
Layout Containers
Controls need to be placed inside layout containers that manage their positioning.
VBox – Vertical Stack
Arranges children top-to-bottom with optional spacing.
VBox form = new VBox(10); // 10px spacing between children
form.setPadding(new Insets(20));
form.getChildren().addAll(nameField, gradeBox, addBtn, result);
HBox – Horizontal Row
Arranges children left-to-right.
HBox buttonRow = new HBox(10);
buttonRow.getChildren().addAll(addBtn, deleteBtn, clearBtn);
BorderPane – Five Regions
Divides the window into top, bottom, left, right, and center. Ideal for standard app layouts.
BorderPane layout = new BorderPane();
layout.setTop(title);
layout.setCenter(outputArea);
layout.setBottom(buttonRow);
GridPane – Row/Column Grid
Places controls in specific row/column positions. Good for forms.
GridPane grid = new GridPane();
grid.setHgap(10);
grid.setVgap(10);
grid.setPadding(new Insets(20));
grid.add(new Label("Name:"), 0, 0); // column 0, row 0
grid.add(nameField, 1, 0); // column 1, row 0
grid.add(new Label("Grade:"), 0, 1); // column 0, row 1
grid.add(gradeBox, 1, 1); // column 1, row 1
Choose the simplest layout that works. For most IA projects, a BorderPane with VBox/HBox inside is enough. You do not need to use all layout types.
Event Handling
Events are how your program responds to user actions (clicking a button, pressing Enter, selecting an item).
Lambda Syntax (Recommended)
The simplest way to handle events uses a lambda expression:
addBtn.setOnAction(event -> {
// code that runs when button is clicked
String name = nameField.getText();
if (!name.isEmpty()) {
result.setText("Added: " + name);
nameField.clear();
}
});
Handling Enter Key on TextField
nameField.setOnAction(event -> {
// runs when user presses Enter in the text field
addBtn.fire(); // trigger the button's action
});
ComboBox Selection Change
gradeBox.setOnAction(event -> {
String grade = gradeBox.getValue();
result.setText("Selected: " + grade);
});
Keep event handlers short. If the logic is more than 5-6 lines, extract it into a separate method. This makes your code easier to read and maintain.
Alerts and Dialogs
Alerts are popup windows for messages, confirmations, or errors.
Information Alert
Alert info = new Alert(Alert.AlertType.INFORMATION);
info.setTitle("Success");
info.setHeaderText(null);
info.setContentText("Student added successfully.");
info.showAndWait();
Confirmation Alert
Returns the user’s choice (OK or Cancel):
Alert confirm = new Alert(Alert.AlertType.CONFIRMATION);
confirm.setTitle("Confirm Delete");
confirm.setHeaderText(null);
confirm.setContentText("Delete this student? This cannot be undone.");
if (confirm.showAndWait().get() == ButtonType.OK) {
// user clicked OK -- proceed with delete
}
Error Alert
Alert error = new Alert(Alert.AlertType.ERROR);
error.setTitle("Error");
error.setHeaderText(null);
error.setContentText("Name field cannot be empty.");
error.showAndWait();
Use alerts sparingly. For validation feedback (e.g., “name is required”), updating a label is often better than showing a popup. Reserve alerts for confirmations and critical errors.
Putting It Together
Here is a complete mini-application that lets the user add names to a list and display them.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.util.ArrayList;
public class NameListApp extends Application {
private ArrayList<String> names = new ArrayList<>();
private TextArea display = new TextArea();
@Override
public void start(Stage stage) {
Label title = new Label("Name List Manager");
TextField nameField = new TextField();
nameField.setPromptText("Enter a name");
Button addBtn = new Button("Add");
Button clearBtn = new Button("Clear All");
Label status = new Label("");
addBtn.setOnAction(event -> {
String name = nameField.getText().trim();
if (name.isEmpty()) {
status.setText("Please enter a name.");
} else {
names.add(name);
nameField.clear();
status.setText("Added: " + name);
refreshDisplay();
}
});
nameField.setOnAction(event -> addBtn.fire());
clearBtn.setOnAction(event -> {
Alert confirm = new Alert(Alert.AlertType.CONFIRMATION);
confirm.setTitle("Confirm");
confirm.setHeaderText(null);
confirm.setContentText("Clear all names?");
if (confirm.showAndWait().get() == ButtonType.OK) {
names.clear();
status.setText("List cleared.");
refreshDisplay();
}
});
display.setEditable(false);
display.setPrefRowCount(10);
HBox buttons = new HBox(10, addBtn, clearBtn);
VBox form = new VBox(10, nameField, buttons, status);
form.setPadding(new Insets(10));
BorderPane root = new BorderPane();
root.setTop(title);
root.setCenter(display);
root.setBottom(form);
root.setPadding(new Insets(10));
Scene scene = new Scene(root, 400, 400);
stage.setTitle("Name List Manager");
stage.setScene(scene);
stage.show();
}
private void refreshDisplay() {
display.clear();
for (int i = 0; i < names.size(); i++) {
display.appendText((i + 1) + ". " + names.get(i) + "\n");
}
}
public static void main(String[] args) {
launch(args);
}
}
What this demonstrates:
- Stage/Scene setup with a
BorderPanelayout TextFieldfor input with prompt textButtonwith event handlers using lambdasTextAreaas a read-only display areaAlertfor confirmation before destructive actionArrayListas the data store (replaced by file I/O in a real IA)- Separation of display refresh into its own method
Common Patterns for IA Projects
Input Validation
Always validate user input before processing:
addBtn.setOnAction(event -> {
String name = nameField.getText().trim();
if (name.isEmpty()) {
status.setText("Error: Name cannot be empty.");
return; // stop here -- do not add
}
if (name.length() > 50) {
status.setText("Error: Name too long (max 50 characters).");
return;
}
// input is valid -- proceed
names.add(name);
nameField.clear();
status.setText("Added: " + name);
refreshDisplay();
});
Disabling Controls
Disable buttons when an action is not valid:
deleteBtn.setDisable(true); // greyed out initially
// Enable when something is selected
listView.getSelectionModel().selectedItemProperty().addListener(
(obs, oldVal, newVal) -> deleteBtn.setDisable(newVal == null)
);
Updating a Status Label
Use a status label at the bottom of the form to give the user feedback without popups:
status.setText("Ready"); // default state
status.setText("Added: " + name); // after successful action
status.setText("Error: invalid input"); // on validation failure
Quick Check
Q1. In JavaFX, which class represents the application window?
Q2. Which method is called automatically when a JavaFX application starts?
Q3. How do you read the text a user has typed into a TextField?
Q4. Which layout container arranges its children in a vertical stack?
Q5. Which method displays an Alert and waits for the user to respond?
Code Completion
Complete the missing parts of this JavaFX application.
Fill in the blanks: Complete this JavaFX application that shows a greeting when the button is clicked.
public class GreetApp extends {
@Override
public void start( stage) {
TextField nameField = new TextField();
Label output = new Label("");
Button greetBtn = new Button("Greet");
greetBtn.setOnAction(event -> {
String name = nameField.;
output.setText("Hello, " + name + "!");
});
VBox root = new VBox(10, nameField, greetBtn, output);
Scene scene = new (root, 300, 200);
stage.setScene(scene);
stage.;
}
} Spot the Error
This JavaFX code should display a window, but nothing appears when it runs.
Bug Hunt: The application runs without errors but no window appears. Find the missing step.
Pick the correct fix for line 7:
Predict the Output
Predict: The user types "Alice" into nameField and clicks the button. What text does the result label show?
Button btn = new Button("Greet");
Label result = new Label("");
btn.setOnAction(event -> {
String name = nameField.getText();
result.setText("Hello, " + name + "!");
nameField.clear();
}); Practice Exercises
Core
-
Hello App – Create a JavaFX application with a
TextField, aButtonlabelled “Say Hello”, and aLabel. When the button is clicked, the label should display “Hello, [name]!” where [name] is whatever was typed in the text field. -
Counter App – Create an application with a
Labelshowing a number (starting at 0) and two buttons: “+” and “-“. Clicking “+” increments the number, clicking “-“ decrements it. The label should update after each click.
Extension
-
Temperature Converter – Create an app with a
TextFieldfor input, aComboBoxto select the conversion direction (Celsius to Fahrenheit or Fahrenheit to Celsius), a “Convert” button, and aLabelfor the result. Validate that the input is a valid number before converting. -
To-Do List – Create an app where users can type a task, add it to a
TextAreadisplay, and clear all tasks (with a confirmation alert). Number each task automatically (1, 2, 3…).
Challenge
- Student Register – Build a form with fields for name, grade (ComboBox: 11 or 12), and HL/SL (CheckBox). Add a “Register” button that validates all fields are filled and displays the student information in a
TextArea. Add a “Clear Form” button that resets all fields to their defaults.
Connections
- Prerequisites: Classes and Objects – JavaFX apps are classes that extend
Application - Prerequisites: Encapsulation – controls use getters/setters (
getText(),setText()) - Next: MVC Architecture – separating data, display, and logic
- Next: FXML and Controllers – defining UI in XML instead of Java code
- Next: File I/O in Apps – saving and loading data