Question

I'm looking for form validator similar to these examples:

enter image description here

or

enter image description here

Is this custom JavaFX component or this can be done using standard JavaFX?

Is there any example how I can create form validator similar to these?

Was it helpful?

Solution

Just to give you a kick start, here is a small example with using ContextMenu. May be ContextMenu is not an ideal Control for this scenario and you are free to replace it with Label, Text etc. Keep the TextField and Label inside a HBox (with Label being hidden initially) and the HBox into the GridPane. Or, you may use any other method all together !

You can design the validation messages/controls with CSS !

Just to add (May be you are aware of this):

Functionally, it depends on you, when do you want to trigger the validation and what should your validation condition be. In my example, I am checking for empty Textfields and I have triggered the validation on the click of the Sign in button. You can trigger the validation, under similar scenario or, on removing focus from any TextField or, some other scenario !

There are various approaches to what you are looking for and javafx being so rich in UI controls and design, it completely depends on your creativity !

ValidationDemo.java

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Side;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.stage.Stage;

public class ValidationDemo extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        stage.setTitle("Validation Demo");
        BorderPane borderPane = new BorderPane();

        borderPane.setCenter(loadLoginScreen());
        Scene scene = new Scene(borderPane, 700, 500);
        scene.getStylesheets().add(
                ValidationDemo.class.getResource("context.css")
                        .toExternalForm());
        stage.setScene(scene);
        stage.show();
    }

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

    private GridPane loadLoginScreen() {

        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25, 25, 25, 25));

        Text scenetitle = new Text("Welcome");
        scenetitle.setFont(Font.font("Tahoma", FontWeight.NORMAL, 20));
        grid.add(scenetitle, 0, 0, 2, 1);

        Label userName = new Label("User Name:");
        grid.add(userName, 0, 1);

        final TextField userTextField = new TextField();
        grid.add(userTextField, 1, 1);

        Label pw = new Label("Password:");
        grid.add(pw, 0, 2);

        final PasswordField pwBox = new PasswordField();
        grid.add(pwBox, 1, 2);

        Button btn = new Button("Sign in");
        HBox hbBtn = new HBox(10);
        hbBtn.setAlignment(Pos.BOTTOM_RIGHT);
        hbBtn.getChildren().add(btn);
        grid.add(hbBtn, 1, 4);

        final Text actiontarget = new Text();
        grid.add(actiontarget, 1, 6);

        // Context Menu for error messages
        final ContextMenu usernameValidator = new ContextMenu();
        usernameValidator.setAutoHide(false);
        final ContextMenu passValidator = new ContextMenu();
        passValidator.setAutoHide(false);

        // Action on button press
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent e) {
                // Clearing message if any
                actiontarget.setText("");

                // Checking if the userTextField is empty
                if (userTextField.getText().equals("")) {
                    usernameValidator.getItems().clear();
                    usernameValidator.getItems().add(
                            new MenuItem("Please enter username"));
                    usernameValidator.show(userTextField, Side.RIGHT, 10, 0);
                }
                // Checking if the pwBox is empty
                if (pwBox.getText().equals("")) {
                    passValidator.getItems().clear();
                    passValidator.getItems().add(
                            new MenuItem("Please enter Password"));
                    passValidator.show(pwBox, Side.RIGHT, 10, 0);
                }
                // If both of the above textFields have values
                if (!pwBox.getText().equals("")
                        && !userTextField.getText().equals("")) {
                    actiontarget.setFill(Color.GREEN);
                    actiontarget.setText("Welcome");
                }
            }
        });

        userTextField.focusedProperty().addListener(
                new ChangeListener<Boolean>() {
                    @Override
                    public void changed(
                            ObservableValue<? extends Boolean> arg0,
                            Boolean oldPropertyValue, Boolean newPropertyValue) {
                        if (newPropertyValue) {
                            // Clearing message if any
                            actiontarget.setText("");
                            // Hiding the error message
                            usernameValidator.hide();
                        }
                    }
                });

        pwBox.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> arg0,
                    Boolean oldPropertyValue, Boolean newPropertyValue) {
                if (newPropertyValue) {
                    // Clearing message if any
                    actiontarget.setText("");
                    // Hiding the error message
                    passValidator.hide();
                }
            }
        });
        return grid;
    }

}

context.css

.root {
  -fx-background-color: cornsilk; 
  -fx-padding: 10;
}

.context-menu {
  -fx-background-color: #006699;
  -fx-text-fill: white;
  -fx-padding: 0;
}

.context-menu:hover {
  -fx-background-color: #006699;
  -fx-text-fill: white;
}

.menu-item .label {
  -fx-text-fill: white;
}

.menu-item:focused .label {
  -fx-text-fill: white;
}

OTHER TIPS

Now there is a library called JFoenix that has JavaFX nodes with material design, it also implements some utilities like a TextField validator, but for their own material textfield which is JFXTextField, and that's how it looks:

you can also add an image to it like an alert icon if you want.

Here is how you would do it:

JFXTextField validationField = new JFXTextField();
RequiredFieldValidator validator = new RequiredFieldValidator();
validator.setMessage("Input Required");
validationField.getValidators().add(validator);
validationField.focusedProperty().addListener((o,oldVal,newVal)->{
    if(!newVal) validationField.validate();
});

Here the RequiredFieldValidator checks whether the textfield is empty, other validators are RegexValidator,DoubleValidator, IntegerValidator and NumberValidator.

source: JFoenix

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top