Dialogs and feedback
IA tooling, not an exam topic. These are JavaFX patterns to adapt for your IA app. Nothing here is examinable, and your IA must be your own work, so change the messages and actions to fit your project.
This page is about talking back to the user: telling them something, asking before you do something risky, and handling input that does not make sense.
New here? Read Start here: how every recipe fits together first; it explains the two places you edit and the fx:id and onAction links every recipe relies on.
Tell the user something
What this does: shows a small pop-up message with an OK button, then waits for the user to close it before the program carries on.
When you would use it in your IA: confirming a save worked, reporting that a search found no results, or telling the user a task finished. Anything where a one-line message is enough.
In SceneBuilder (the layout): nothing to add beyond a button to trigger it. Add a Button, set its onAction to handleSave (or reuse the button you already have for the action). The dialog itself is created in code.
<Button text="Save" onAction="#handleSave" />
In the controller (the .java file):
Imports:
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
Controller method:
@FXML
private void handleSave() {
// your IA logic here: do the actual work (save the data, run the task)
saveData();
Alert info = new Alert(AlertType.INFORMATION);
info.setTitle("Saved");
info.setHeaderText(null); // null removes the bold banner line
info.setContentText("Your changes have been saved.");
info.showAndWait();
}
Where your own logic goes: the line marked // your IA logic here, where you do the real work before reporting it. The dialog is reusable wiring.
Make it your own:
- Change the title and the
setContentTextmessage to match what happened. setHeaderText(null)gives a clean one-line dialog. Pass a short string instead if you want a bold heading above the message.- Swap
AlertType.INFORMATIONforAlertType.WARNINGorAlertType.ERRORto change the icon when the message is a caution or a failure.
Watch out for:
- The method named in
onAction(handleSave) must exist in the controller, or the screen will not load. showAndWait()blocks until the user closes the dialog, which is what you usually want. If you call it from inside a long loop, the user has to click OK every time around, so keep these for single moments, not bulk output.
Mix with: Ask before doing something destructive, Catch and explain bad input, Save and load text.
Ask before doing something that cannot be undone
What this does: shows a confirmation dialog and only runs the risky action if the user clicks OK. Stops accidental clicks from wiping data.
When you would use it in your IA: any button that deletes a record, clears a list, resets a form, or overwrites a file. Wrap the action so the user has to confirm first.
In SceneBuilder (the layout): you need a button to trigger the action. Add a Button, give it an fx:id such as btnDelete, and set its onAction to handleDelete. The confirmation window itself is created in code, so there is nothing else to add here.
<Button fx:id="btnDelete" text="Delete" onAction="#handleDelete" />
In the controller (the .java file):
Imports:
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import java.util.Optional;
Controller method:
@FXML
private void handleDelete(ActionEvent event) {
Alert confirm = new Alert(AlertType.CONFIRMATION);
confirm.setTitle("Please confirm");
confirm.setHeaderText(null);
confirm.setContentText("Are you sure you want to delete this item?");
Optional<ButtonType> result = confirm.showAndWait();
if (result.isPresent() && result.get() == ButtonType.OK) {
// your IA logic here: the action that cannot be undone
removeSelectedItem();
}
// If the user clicked Cancel, nothing happens.
}
Where your own logic goes: inside the if block, on the line marked // your IA logic here. That is the one spot you change for your own app; everything else is reusable wiring.
Make it your own:
- Change the message in
setContentTextto describe your own action. - Replace
removeSelectedItem()with whatever your risky action is. - Keep the
ifcheck exactly as it is. That is the part that makes the guard work.
Watch out for:
- The
fx:idin the layout (btnDelete) and the method named inonAction(handleDelete) must match the controller exactly, or the screen will not load. showAndWait()returns anOptional, which may be empty if the dialog is closed in an unusual way. TheisPresent()check handles that, so keep it.- Put the real action inside the
ifblock, not after it, or it will run even when the user cancels.
Mix with: Find out which row the user clicked, Tell the user something, Save and load text.
Catch and explain bad input
What this does: tries to read a number from a text field, and if the text is not a number, shows a clear message and sends the cursor back to the field instead of crashing.
When you would use it in your IA: any field where the user types a quantity, age, price, or score that your code then converts with Integer.parseInt or Double.parseDouble. A typed letter or a blank field would otherwise throw an exception.
In SceneBuilder (the layout): add the field the user types into (fx:id txtQuantity), a label to show errors in (fx:id lblError), and a button that runs the action (onAction handleAdd).
<TextField fx:id="txtQuantity" />
<Label fx:id="lblError" textFill="red" />
<Button text="Add" onAction="#handleAdd" />
In the controller (the .java file):
Imports:
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
Controller:
@FXML private TextField txtQuantity;
@FXML private Label lblError;
@FXML
private void handleAdd() {
try {
int quantity = Integer.parseInt(txtQuantity.getText().trim());
lblError.setText(""); // clear any old error
// your IA logic here: use the validated number
addItems(quantity);
} catch (NumberFormatException e) {
lblError.setText("Please enter a whole number.");
txtQuantity.requestFocus(); // put the cursor back so they can fix it
}
}
Where your own logic goes: the line marked // your IA logic here, which runs only once the input is a valid number. The parsing, the error message, and the focus-return are reusable wiring.
Make it your own:
- Change the error message to name what you expected.
- Use
Double.parseDoubleinstead for prices or measurements. lblErroris an inlineLabelnear the field. You could show anAlertType.ERRORdialog instead if you prefer a pop-up.
Watch out for:
- The
fx:idvalues (txtQuantity,lblError) must match the@FXMLfield names, andhandleAddmust exist in the controller, or the screen will not load. - Catch
NumberFormatExceptionspecifically, not a bareException. Catching everything hides real bugs. - An empty field throws the same exception as a typed letter, so this one
catchcovers both cases. - This is input validation, the same idea you use on forms. Pair it with Allow only numbers in a field to stop bad input before it is ever typed.
Mix with: Allow only numbers in a field, Turn a control on or off, Tell the user something.