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:

  1. launch() creates the Application and calls start()
  2. start() receives the primary Stage (window)
  3. We create controls, put them in a layout, wrap the layout in a Scene
  4. 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).

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 BorderPane layout
  • TextField for input with prompt text
  • Button with event handlers using lambdas
  • TextArea as a read-only display area
  • Alert for confirmation before destructive action
  • ArrayList as 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.

1public void start(Stage stage) { 2 Label label = new Label("Hello!"); 3 VBox root = new VBox(label); 4 Scene scene = new Scene(root, 300, 200); 5 stage.setTitle("My App"); 6 stage.setScene(scene); 7 // window should appear here 8}

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

  1. Hello App – Create a JavaFX application with a TextField, a Button labelled “Say Hello”, and a Label. When the button is clicked, the label should display “Hello, [name]!” where [name] is whatever was typed in the text field.

  2. Counter App – Create an application with a Label showing a number (starting at 0) and two buttons: “+” and “-“. Clicking “+” increments the number, clicking “-“ decrements it. The label should update after each click.

Extension

  1. Temperature Converter – Create an app with a TextField for input, a ComboBox to select the conversion direction (Celsius to Fahrenheit or Fahrenheit to Celsius), a “Convert” button, and a Label for the result. Validate that the input is a valid number before converting.

  2. To-Do List – Create an app where users can type a task, add it to a TextArea display, and clear all tasks (with a confirmation alert). Number each task automatically (1, 2, 3…).

Challenge

  1. 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


© EduCS.me — A resource hub for Computer Science education

This site uses Just the Docs, a documentation theme for Jekyll.