This is the second post of my JavaFX tutorial series. In the previous post, we created a simple Hello World application and learned about JavaFX application lifecyle.

If you are a beginner in JavaFX and want to understand the basics, I encourage you to go through my previous post before reading this one.

In this post, We’ll create an interactive javafx application with multiple UI controls.

The application will have a registration form where users can enter their details and then submit the form. When the user submits the form, we’ll greet him by showing an alert box.

Here is a screenshot of the application that we are going to build in this tutorial -

JavaFX Registration Form Example

What will you learn?

In this blog post, you’ll learn -

  • How to create the layout of a JavaFX application window.

  • How to add UI controls like Text Field, Password Field, and Button.

  • How to respond to input events.

Cool! Let’s get started.

Create the Main Application class

The first thing you need to do is to create the Main class for your JavaFX application which extends javafx.application.Application, and override it’s start() method.

Open your favorite IDE and create a new Java project along with a class named RegistrationFormApplication with the following contents -

import javafx.application.Application;
import javafx.stage.Stage;

public class RegistrationFormApplication extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Registration Form JavaFX Application");
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Create the Layout of your application

JavaFX provides layout container classes, called panes, to easily manage the user interface of your application. Layout panes allow you to add UI controls and position them on the screen.

We will use a GridPane layout for designing our registration form. GridPane layout enables you to create a flexible grid of rows and columns in which UI nodes can be laid out.

Let’s create our Registration Form layout pane -

private GridPane createRegistrationFormPane() {
    // Instantiate a new Grid Pane
    GridPane gridPane = new GridPane();

    // Position the pane at the center of the screen, both vertically and horizontally
    gridPane.setAlignment(Pos.CENTER);

    // Set a padding of 20px on each side
    gridPane.setPadding(new Insets(40, 40, 40, 40));

    // Set the horizontal gap between columns
    gridPane.setHgap(10);

    // Set the vertical gap between rows
    gridPane.setVgap(10);

    // Add Column Constraints

    // columnOneConstraints will be applied to all the nodes placed in column one.
    ColumnConstraints columnOneConstraints = new ColumnConstraints(100, 100, Double.MAX_VALUE);
    columnOneConstraints.setHalignment(HPos.RIGHT);

    // columnTwoConstraints will be applied to all the nodes placed in column two.
    ColumnConstraints columnTwoConstrains = new ColumnConstraints(200,200, Double.MAX_VALUE);
    columnTwoConstrains.setHgrow(Priority.ALWAYS);

    gridPane.getColumnConstraints().addAll(columnOneConstraints, columnTwoConstrains);
    
    return gridPane;
}

Whoa! Let’s understand what’s going on here.

We first instantiate a new GridPane, and then set the alignment and padding properties. We also add gaps between columns and rows of the grid pane by setting Hgap and Vgap properties.

I have also applied some column constraints to the grid pane. The ColumnConstraints constructor takes the min width, preferred width and max width values.

All the nodes in column one will have a min-width of 100, pref-width of 100 and max-width of Double.MAX_VALUE.

Similarly, all the nodes in column two will have a min-width of 200, pref-width of 200 and max-width of Double.MAX_VALUE.

Also, I have set the Halignment property to HPos.RIGHT in columnOneConstraints so that all the nodes in column 1 are right aligned.

Moreover, by setting Hgrow property to Priority.ALWAYS in columnTwoConstraints, we’re specifying that if the screen resizes, then column 2 should grow horizontally and fill in the extra space.

Create a Scene

Let’s now create a scene with the registration form grid pane as the root node. Modify the start() method of the main class so that it looks like this -

@Override
public void start(Stage primaryStage) throws Exception {
    primaryStage.setTitle("Registration Form JavaFX Application");

    // Create the registration form pane
    GridPane gridPane = createRegistrationFormPane();
    // Create a scene with the registration form gridPane as the root node.
    Scene scene = new Scene(gridPane, 800, 500);
    // Set the scene in primary stage
    primaryStage.setScene(scene);
    
    primaryStage.show();
}

If you run the application now, you’ll get an empty window of width 800 and height 500. In the next section, We’ll add UI controls to the application.

Add UI Controls to the layout.

JavaFX provides several built-in GUI controls like TextField, PasswordField, Button etc. Let’s add these UI controls to our registration form pane -

private void addUIControls(GridPane gridPane) {
    // Add Header
    Label headerLabel = new Label("Registration Form");
    headerLabel.setFont(Font.font("Arial", FontWeight.BOLD, 24));
    gridPane.add(headerLabel, 0,0,2,1);
    GridPane.setHalignment(headerLabel, HPos.CENTER);
    GridPane.setMargin(headerLabel, new Insets(20, 0,20,0));

    // Add Name Label
    Label nameLabel = new Label("Full Name : ");
    gridPane.add(nameLabel, 0,1);

    // Add Name Text Field
    TextField nameField = new TextField();
    nameField.setPrefHeight(40);
    gridPane.add(nameField, 1,1);


    // Add Email Label
    Label emailLabel = new Label("Email ID : ");
    gridPane.add(emailLabel, 0, 2);

    // Add Email Text Field
    TextField emailField = new TextField();
    emailField.setPrefHeight(40);
    gridPane.add(emailField, 1, 2);

    // Add Password Label
    Label passwordLabel = new Label("Password : ");
    gridPane.add(passwordLabel, 0, 3);

    // Add Password Field
    PasswordField passwordField = new PasswordField();
    passwordField.setPrefHeight(40);
    gridPane.add(passwordField, 1, 3);

    // Add Submit Button
    Button submitButton = new Button("Submit");
    submitButton.setPrefHeight(40);
    submitButton.setDefaultButton(true);
    submitButton.setPrefWidth(100);
    gridPane.add(submitButton, 0, 4, 2, 1);
    GridPane.setHalignment(submitButton, HPos.CENTER);
    GridPane.setMargin(submitButton, new Insets(20, 0,20,0));
}

The gridPane.add() method takes the columnIndex, rowIndex, colSpan and rowSpan arguments. You can add UI controls to any cell in the grid by using these arguments. columnIndex and rowIndex starts from zero.

The headerLabel is placed on the first cell (columnIndex : 0, rowIndex : 0) and spans two columns. We have also added horizontal alignment and some margin to the headerLabel.

The Name, Email and Password fields are placed in subsequent rows. All the labels are placed in the first column and the input fields are placed in the second column.

Add the handler code that is executed on form submit.

Let’s now add our handler code to the submit button. This handler is invoked whenever you click Submit button, or press Enter key -

submitButton.setOnAction(new EventHandler<ActionEvent>() {
    @Override
    public void handle(ActionEvent event) {
        if(nameField.getText().isEmpty()) {
            showAlert(Alert.AlertType.ERROR, gridPane.getScene().getWindow(), 
            "Form Error!", "Please enter your name");
            return;
        }
        if(emailField.getText().isEmpty()) {
            showAlert(Alert.AlertType.ERROR, gridPane.getScene().getWindow(), 
            "Form Error!", "Please enter your email id");
            return;
        }
        if(passwordField.getText().isEmpty()) {
            showAlert(Alert.AlertType.ERROR, gridPane.getScene().getWindow(), 
            "Form Error!", "Please enter a password");
            return;
        }

        showAlert(Alert.AlertType.CONFIRMATION, gridPane.getScene().getWindow(), 
        "Registration Successful!", "Welcome " + nameField.getText());
    }
});

The setOnAction() method is used to register an event handler to a UI control.

In the above handler code, we show an error alert if any of the form fields are missing, otherwise, we show a confirmation alert to the user.

We use JavaFX’s built-in Alert class to show the alert boxes to the user. Following is the implementation of showAlert() method. -

private void showAlert(Alert.AlertType alertType, Window owner, String title, String message) {
    Alert alert = new Alert(alertType);
    alert.setTitle(title);
    alert.setHeaderText(null);
    alert.setContentText(message);
    alert.initOwner(owner);
    alert.show();
}

Complete Code and Output

Here is the complete code for your reference -

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
import javafx.stage.Window;

public class RegistrationFormApplication extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        primaryStage.setTitle("Registration Form JavaFX Application");

        // Create the registration form grid pane
        GridPane gridPane = createRegistrationFormPane();
        // Add UI controls to the registration form grid pane
        addUIControls(gridPane);
        // Create a scene with registration form grid pane as the root node
        Scene scene = new Scene(gridPane, 800, 500);
        // Set the scene in primary stage	
        primaryStage.setScene(scene);
        
        primaryStage.show();
    }


    private GridPane createRegistrationFormPane() {
        // Instantiate a new Grid Pane
        GridPane gridPane = new GridPane();

        // Position the pane at the center of the screen, both vertically and horizontally
        gridPane.setAlignment(Pos.CENTER);

        // Set a padding of 20px on each side
        gridPane.setPadding(new Insets(40, 40, 40, 40));

        // Set the horizontal gap between columns
        gridPane.setHgap(10);

        // Set the vertical gap between rows
        gridPane.setVgap(10);

        // Add Column Constraints

        // columnOneConstraints will be applied to all the nodes placed in column one.
        ColumnConstraints columnOneConstraints = new ColumnConstraints(100, 100, Double.MAX_VALUE);
        columnOneConstraints.setHalignment(HPos.RIGHT);

        // columnTwoConstraints will be applied to all the nodes placed in column two.
        ColumnConstraints columnTwoConstrains = new ColumnConstraints(200,200, Double.MAX_VALUE);
        columnTwoConstrains.setHgrow(Priority.ALWAYS);

        gridPane.getColumnConstraints().addAll(columnOneConstraints, columnTwoConstrains);

        return gridPane;
    }

    private void addUIControls(GridPane gridPane) {
        // Add Header
        Label headerLabel = new Label("Registration Form");
        headerLabel.setFont(Font.font("Arial", FontWeight.BOLD, 24));
        gridPane.add(headerLabel, 0,0,2,1);
        GridPane.setHalignment(headerLabel, HPos.CENTER);
        GridPane.setMargin(headerLabel, new Insets(20, 0,20,0));

        // Add Name Label
        Label nameLabel = new Label("Full Name : ");
        gridPane.add(nameLabel, 0,1);

        // Add Name Text Field
        TextField nameField = new TextField();
        nameField.setPrefHeight(40);
        gridPane.add(nameField, 1,1);


        // Add Email Label
        Label emailLabel = new Label("Email ID : ");
        gridPane.add(emailLabel, 0, 2);

        // Add Email Text Field
        TextField emailField = new TextField();
        emailField.setPrefHeight(40);
        gridPane.add(emailField, 1, 2);

        // Add Password Label
        Label passwordLabel = new Label("Password : ");
        gridPane.add(passwordLabel, 0, 3);

        // Add Password Field
        PasswordField passwordField = new PasswordField();
        passwordField.setPrefHeight(40);
        gridPane.add(passwordField, 1, 3);

        // Add Submit Button
        Button submitButton = new Button("Submit");
        submitButton.setPrefHeight(40);
        submitButton.setDefaultButton(true);
        submitButton.setPrefWidth(100);
        gridPane.add(submitButton, 0, 4, 2, 1);
        GridPane.setHalignment(submitButton, HPos.CENTER);
        GridPane.setMargin(submitButton, new Insets(20, 0,20,0));

        submitButton.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                if(nameField.getText().isEmpty()) {
                    showAlert(Alert.AlertType.ERROR, gridPane.getScene().getWindow(), "Form Error!", "Please enter your name");
                    return;
                }
                if(emailField.getText().isEmpty()) {
                    showAlert(Alert.AlertType.ERROR, gridPane.getScene().getWindow(), "Form Error!", "Please enter your email id");
                    return;
                }
                if(passwordField.getText().isEmpty()) {
                    showAlert(Alert.AlertType.ERROR, gridPane.getScene().getWindow(), "Form Error!", "Please enter a password");
                    return;
                }

                showAlert(Alert.AlertType.CONFIRMATION, gridPane.getScene().getWindow(), "Registration Successful!", "Welcome " + nameField.getText());
            }
        });
    }

    private void showAlert(Alert.AlertType alertType, Window owner, String title, String message) {
        Alert alert = new Alert(alertType);
        alert.setTitle(title);
        alert.setHeaderText(null);
        alert.setContentText(message);
        alert.initOwner(owner);
        alert.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Following is the final form (Pretty! isn’t it?) -

JavaFX layout registration form example

Once user clicks submit, a confirmation alert is shown -

JavaFX layout registration form confirmation example

Showing error if any form field is missing -

JavaFX layout registration form error example

Conclusion

In this blog post, we learned about JavaFX layout design and created a nice looking interactive registration form using GridPane layout. The code for the Registration Form application can be found on my github repository.

In the next blog post, I’ll show you how to build the same application using JavaFX FXML.

Thank you for reading. Please ask your doubts in the comment section below.