Java Arena
Step 2 of 8

A form and its result

A common pair of views: a form, where the user types something, and a result, which shows what the program made of it. The handler of the form's button reads the fields, fills in the result and switches to it.

A postcard

A holiday app writes postcards. The form has a field for whom the card is for and a text area for the message; the card shows them:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage stage) {
        TextField to = new TextField();
        to.setPromptText("To");
        TextArea message = new TextArea();
        Button preview = new Button("Preview");
        Scene form = new Scene(new VBox(8, to, message, preview));

        Label greeting = new Label("");
        Label text = new Label("");
        Button edit = new Button("Edit");
        Scene card = new Scene(new VBox(8, greeting, text, edit));

        preview.setOnAction(event -> {
            greeting.setText("Dear " + to.getText() + ",");
            text.setText(message.getText());
            stage.setScene(card);
        });
        edit.setOnAction(event -> stage.setScene(form));

        stage.setScene(form);
        stage.setTitle("Postcard");
        stage.show();
    }

    public static void main(String[] args) {
        launch(Main.class);
    }
}
The window

After: Type "Ada" in text field 1, type "The lake is warm. See you soon!" in text area 1, then click "Preview"

This window is wider than the screen: scroll it sideways, or read it as text below.

The window as text
Window "Postcard"
  VBox spacing 8
    Label "Dear Ada,"
    Label "The lake is warm. See you soon!"
    Button "Edit"
  • Both scenes are built in start. The card's labels start empty: there's nothing to show before the user has written anything.
  • The handler of Preview reads the field and the text area when it runs, so it gets what the user has typed by then (module 49). It sets the card's labels from them, and then shows the card.
  • Edit shows the form again, and the form still holds what was typed, since it's the same scene with the same field and text area. The user can change the message and preview it again.

Refusing empty input

With the field empty, the card says Dear ,. A form should refuse that and say what's missing, without leaving the form. The form gets an empty label for messages, and the handler checks the field first:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage stage) {
        TextField to = new TextField();
        to.setPromptText("To");
        TextArea message = new TextArea();
        Button preview = new Button("Preview");
        Label error = new Label("");
        Scene form = new Scene(new VBox(8, to, message, preview, error));

        Label greeting = new Label("");
        Label text = new Label("");
        Button edit = new Button("Edit");
        Scene card = new Scene(new VBox(8, greeting, text, edit));

        preview.setOnAction(event -> {
            if (to.getText().trim().isEmpty()) {
                error.setText("Write who the card is for.");
            } else {
                greeting.setText("Dear " + to.getText().trim() + ",");
                text.setText(message.getText());
                error.setText("");
                stage.setScene(card);
            }
        });
        edit.setOnAction(event -> stage.setScene(form));

        stage.setScene(form);
        stage.setTitle("Postcard");
        stage.show();
    }

    public static void main(String[] args) {
        launch(Main.class);
    }
}
The window

After: Type "Greetings from the lake!" in text area 1, then click "Preview"

This window is wider than the screen: scroll it sideways, or read it as text below.

The window as text
Window "Postcard"
  VBox spacing 8
    TextField "", prompt "To"
    TextArea "Greetings from the lake!"
    Button "Preview"
    Label "Write who the card is for."
  • trim() removes the spaces at the ends (module 16), so a field with only spaces counts as empty too.
  • When the field is empty, the handler sets the message and does nothing else: the window stays on the form, and the user can fix it.
  • When the field has a name, the handler empties the message before it switches. Otherwise the old message would still be there when Edit brings the form back.

Building the result in the handler

The card above is built once, and the handler only changes the texts of its labels. A handler can also build the result scene itself, each time it runs:

preview.setOnAction(event -> {
    Label greeting = new Label("Dear " + to.getText().trim() + ",");
    VBox card = new VBox(8, greeting, new Label(message.getText()));
    stage.setScene(new Scene(card));
});

Each click makes a new card, with new labels and a new scene. That's handy when the result's shape depends on the input, such as a label for each line the user wrote, and the third challenge below needs it. A view that is built once keeps its state between visits; a view that is built in the handler starts fresh every time.

Your task

Challenge 1 of 3

A pet hotel checks pets in. Both scenes are built already, each a VBox with the spacing 8:

  • the form: the label Pet's name, a text field, the button Check in and an empty label for messages
  • the room: an empty label and the button Next pet

Give the buttons their handlers:

  • Check in: when the field is empty (or has only spaces), the message label says Type the pet's name first. and the window stays on the form. Otherwise the room's label says which room is ready, like Room 1 is ready for Rex. (with the name trimmed), and the window shows the room scene. The rooms are numbered from 1, in the order the pets check in: keep the count in an instance variable of Main.
  • Next pet: empties the text field and the message label, and shows the form again.

The task card shows the window after typing Rex and clicking Check in.

Challenge 2

A restaurant books tables online. The form is a VBox with the spacing 8 holding the label Guests, a text field, the button Book and an empty label for messages. The booked scene is a VBox with the spacing 8 holding an empty label and the button Change. Both are built already: write the handlers.

Book reads the number of guests from the field and checks it, in this order:

  • not a whole number (Integer.valueOf throws a NumberFormatException, module 42): the message is Type the number of guests in digits.
  • below 1: At least 1 guest, please.
  • above 8: For more than 8 guests, please call us.
  • otherwise the booked scene's label says A table for 4 is booked. (with the number), the message label is emptied, and the window shows the booked scene.

In the first three cases the window stays on the form. Change shows the form again, with the number still in the field. The task card shows the window after typing 4 and clicking Book.

Challenge 3

A list of errands. The form is a VBox with the spacing 8 holding a text area, the button Make list and an empty label for messages; it's built already. The user writes the day's errands in the text area, one per line.

Make list builds a new scene, each time it's clicked: a VBox with the spacing 4 and no padding, holding for each line of the text area a label with [ ] and the line, trimmed, like [ ] Buy stamps, in the order of the lines, and at the end a new button Edit. Lines that are empty, or have only spaces, get no label. Edit shows the form again. When it builds the list, Make list also empties the message label, so that no old message is left when Edit brings the form back.

When no line has any text, Make list stays on the form and the message label says Write at least one errand.

split("\n") splits the text into its lines. The task card shows the window after writing Buy stamps, Return the books, an empty line and Fix the bike, and clicking Make list.