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.
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 the main JavaFX entry point, where you build and show the first window?
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