Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Dialogs and Alert

A dialog is a small window that asks a question or reports something important and waits for an answer. In JavaFX ready-made dialogs live in javafx.scene.control: Alert for messages and confirmations, TextInputDialog for entering a string, ChoiceDialog for picking from a list. In the notebook, dialogs will warn about an empty title, ask again before deleting and help add a new category.

A warning

The "Add" button is already disabled for an empty field, but it lets a title made of spaces through. Let's show a warning:

// src/main/java/com/example/notes/MainController.java — start of addNote()
String title = titleField.getText().strip();
if (title.isEmpty()) {
    Alert alert = new Alert(Alert.AlertType.WARNING, "The title cannot consist of spaces only.");
    alert.initOwner(table.getScene().getWindow());
    alert.setTitle("Notes");
    alert.setHeaderText("Empty title");
    alert.showAndWait();
    return;
}

Further down in addNote, the ready title variable is used instead of titleField.getText().strip(). The showAndWait() method shows the window and waits until it is closed; the rest of the application window does not respond meanwhile. initOwner ties the dialog to the main window: it appears centered over it and takes its CSS styles, so the dialog buttons are blue. Without setTitle and setHeaderText the title says "Warning".

AlertTypeIconButtons
INFORMATIONiOK
WARNING!OK
ERRORa red crossOK
CONFIRMATION?OK, Cancel
NONEnoneonly the ones you pass

A confirmation

showAndWait() returns an Optional with the clicked button. If the window was closed with the cross, it holds the cancel button:

// src/main/java/com/example/notes/MainController.java — part of deleteNote()
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.initOwner(table.getScene().getWindow());
alert.setTitle("Delete note");
alert.setHeaderText("Delete the note '" + notes.get(index).title() + "'?");
alert.setContentText("This cannot be undone.");
alert.showAndWait()
        .filter(button -> button == ButtonType.OK)
        .ifPresent(button -> notes.remove(index));

The standard buttons are captioned OK and Cancel. JavaFX translates them only into a few languages and shows English for the rest.

Custom buttons

You can create buttons yourself and pass them to the Alert constructor. ButtonData sets the button's role: OK_DONE is the main action, CANCEL_CLOSE is cancel, which is also what the close cross and the Esc key count as:

// src/main/java/com/example/notes/MainController.java — the deleteNote() method
@FXML
private void deleteNote() {
    int index = table.getSelectionModel().getSelectedIndex();
    if (index < 0) {
        return;
    }
    ButtonType delete = new ButtonType("Delete", ButtonBar.ButtonData.OK_DONE);
    ButtonType cancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
    Alert alert = new Alert(Alert.AlertType.CONFIRMATION,
            "This cannot be undone.", delete, cancel);
    alert.initOwner(table.getScene().getWindow());
    alert.setTitle("Delete note");
    alert.setHeaderText("Delete the note '" + notes.get(index).title() + "'?");
    alert.showAndWait()
            .filter(button -> button == delete)
            .ifPresent(button -> notes.remove(index));
}

Select a note and click "Delete". A "Delete note" window appears with a question mark, the question "Delete the note 'Buy milk'?", the line "This cannot be undone." and the "Delete" and "Cancel" buttons. The note disappears only after "Delete".

Entering a string

Let's put a "New..." button next to the category list:

<!-- src/main/resources/com/example/notes/main-view.fxml — instead of the ComboBox line -->
<HBox spacing="8" GridPane.rowIndex="2" GridPane.columnIndex="1">
    <ComboBox fx:id="categoryBox"/>
    <Button text="New..." onAction="#addCategory"/>
</HBox>

TextInputDialog returns an Optional with the entered string:

// src/main/java/com/example/notes/MainController.java — the new addCategory() method
@FXML
private void addCategory() {
    TextInputDialog dialog = new TextInputDialog();
    dialog.initOwner(table.getScene().getWindow());
    dialog.setTitle("New category");
    dialog.setHeaderText("Enter a category name");
    dialog.showAndWait()
            .map(String::strip)
            .filter(name -> !name.isEmpty())
            .ifPresent(name -> {
                categoryBox.getItems().add(name);
                categoryBox.setValue(name);
            });
}

Type "Study" and click OK: the category appears in the list and is selected right away. After Cancel the Optional is empty and nothing happens.

Common mistake

After replacing the standard buttons with your own, people forget to update the check and leave button == ButtonType.OK. The clicked button is now the delete object, the comparison is never true, and the note is not deleted. There is no error; simply nothing happens. Compare with the button you passed to the Alert.

Thanks for reading!

Donate to the site — we work hard for you.