Как ограничить количество символов текстового поля javafx

Im использует FXML для установки моей формы, но мне нужно установить предел символов в текстовых полях. Как я могу сделать это ?

6 ответов


вот мое решение для ограничения длины текстового поля. Я бы не рекомендовал решения, которые используют прослушиватель (по свойству text или по свойству length), они не ведут себя правильно во всех ситуациях (для того, что я видел). Я создаю текст ввода HTML с максимальной длиной и сравниваю его с моим текстовым полем в JavaFX. У меня было такое же поведение с операциями вставки (Ctrl + V), отменой операций (Ctrl + Z) в обоих случаях. Цель здесь-проверить, является ли текст допустимым перед изменением объект TextField. Мы могли бы использовать аналогичный подход для числового текстового поля.

import java.util.Objects;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.control.TextField;   

public class LimitedTextField extends TextField {

    private final IntegerProperty maxLength;

    public LimitedTextField() {
        super();
        this.maxLength = new SimpleIntegerProperty(-1);
    }

    public IntegerProperty maxLengthProperty() {
        return this.maxLength;
    }

    public final Integer getMaxLength() {
        return this.maxLength.getValue();
    }

    public final void setMaxLength(Integer maxLength) {
        Objects.requireNonNull(maxLength, "Max length cannot be null, -1 for no limit");
        this.maxLength.setValue(maxLength);
    }

    @Override
    public void replaceText(int start, int end, String insertedText) {
        if (this.getMaxLength() <= 0) {
            // Default behavior, in case of no max length
            super.replaceText(start, end, insertedText);
        }
        else {
            // Get the text in the textfield, before the user enters something
            String currentText = this.getText() == null ? "" : this.getText();

            // Compute the text that should normally be in the textfield now
            String finalText = currentText.substring(0, start) + insertedText + currentText.substring(end);

            // If the max length is not excedeed
            int numberOfexceedingCharacters = finalText.length() - this.getMaxLength();
            if (numberOfexceedingCharacters <= 0) {
                // Normal behavior
                super.replaceText(start, end, insertedText);
            }
            else {
                // Otherwise, cut the the text that was going to be inserted
                String cutInsertedText = insertedText.substring(
                        0, 
                        insertedText.length() - numberOfexceedingCharacters
                );

                // And replace this text
                super.replaceText(start, end, cutInsertedText);
            }
        }
    }
}

протестировано с JavaFX 8 и Java 8u45


вы не можете напрямую установить ограничение на количество символов. Но вы можете добавить listener to lengthProperty() в поле

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TextFieldLimit extends Application {
    private static final int LIMIT = 10;

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

    @Override
    public void start(final Stage primaryStage) {

        final TextField textField = new TextField();
        textField.lengthProperty().addListener(new ChangeListener<Number>() {

            @Override
            public void changed(ObservableValue<? extends Number> observable,
                    Number oldValue, Number newValue) {
                if (newValue.intValue() > oldValue.intValue()) {
                    // Check if the new character is greater than LIMIT
                    if (textField.getText().length() >= LIMIT) {

                        // if it's 11th character then just setText to previous
                        // one
                        textField.setText(textField.getText().substring(0, LIMIT));
                    }
                }
            }
        });

        VBox vbox = new VBox(20);
        vbox.getChildren().add(textField);

        Scene scene = new Scene(vbox, 400, 300);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
}

еще одно элегантное решение

Pattern pattern = Pattern.compile(".{0,25}");
    TextFormatter formatter = new TextFormatter((UnaryOperator<TextFormatter.Change>) change -> {
        return pattern.matcher(change.getControlNewText()).matches() ? change : null;
    });

    textField.setTextFormatter(formatter);

где 0 и 25 - минимальное и максимальное количество символов. + возможность установить шаблон ввода текста


Это очень простое решение, которое, кажется, работает для меня.

textfield.setOnKeyTyped(event ->{
        int maxCharacters = 5;
        if(tfInput.getText().length() > maxCharacters) event.consume();
    });

Я использую простой вызов ChangeListener, где я тестирую условие для выполнения остановок.

textFild.addListener((observable, oldValue, newValue) -> {
    if (newValue.length() == MAX_SIZE) {
        textField.setText(oldValue);
    }
});

Это лучший способ выполнить работу с общим текстовым полем:

public static void addTextLimiter(final TextField tf, final int maxLength) {
    tf.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(final ObservableValue<? extends String> ov, final String oldValue, final String newValue) {
            if (tf.getText().length() > maxLength) {
                String s = tf.getText().substring(0, maxLength);
                tf.setText(s);
            }
        }
    });
}

работает отлично, за исключением этой ошибки отмены.