Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use JavaFX TextField maxlength

How to use this code in my main class of JavaFX so that I can set maxlength of characters in JavaFX TextField?

class LimitedTextField extends TextField {

    private final int limit;

    public LimitedTextField(int limit) {
        this.limit = limit;
    }

    @Override
    public void replaceText(int start, int end, String text) {
        super.replaceText(start, end, text);
        verify();
    }

    @Override
    public void replaceSelection(String text) {
        super.replaceSelection(text);
        verify();
    }

    private void verify() {
        if (getText().length() > limit) {
            setText(getText().substring(0, limit));
        }

    }
};

My JavaFX main class is given below:

public class TextFiled extends Application {
    @Override
    public void start(Stage primaryStage) {
        final TextField t_fname = new TextField();
        
        StackPane root = new StackPane();
        root.getChildren().add(t_fname);
        
        Scene scene = new Scene(root, 300, 250);
        
        primaryStage.setTitle("Hello World!");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
like image 457
java baba Avatar asked May 14 '13 08:05

java baba


3 Answers

While the OP's technical problem is correctly answered (though not accepted), the solution to the base issue - how to restrict/validate input in a TextField which is answered in the other posts - has changed over time.

With java8u40 we got a new class TextFormatter: one of its main responsibilities is to provide a hook into any change of text input before it gets comitted to the content. To fulfill the requirement of limiting the input to a certain length (and - just for fun - show a context menu with an error message) we would

  • implement a UnaryOperator that analyses all changes
  • reject those which would result into a longer text (and show the message)
  • accept all other changes
  • instantiate a TextFormatter with the operator
  • configure the TextField with the TextFormatter

A code snippet:

int len = 20;
TextField field = new TextField("max chars: " + len );
// here we reject any change which exceeds the length 
UnaryOperator<Change> rejectChange = c -> {
    // check if the change might effect the validating predicate
    if (c.isContentChange()) {
        // check if change is valid
        if (c.getControlNewText().length() > len) {
            // invalid change
            // sugar: show a context menu with error message
            final ContextMenu menu = new ContextMenu();
            menu.getItems().add(new MenuItem("This field takes\n"+len+" characters only."));
            menu.show(c.getControl(), Side.BOTTOM, 0, 0);
            // return null to reject the change
            return null;
        }
    }
    // valid change: accept the change by returning it
    return c;
};
field.setTextFormatter(new TextFormatter(rejectChange));

Aside:

Modifying the state of a sender while it is notifying its listeners about a change of that state is generally a bad idea and might easily lead to unexpected and hard-to-track side-effects (I suspect - though don't know - that the undo bug mentioned in other answers is such a side-effect)

like image 109
kleopatra Avatar answered Sep 24 '22 20:09

kleopatra


This is my solution:

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);
            }
        }
    });
}

See JavaFX 2.2 TextField maxlength and Prefer composition over inheritance?

like image 24
ceklock Avatar answered Sep 22 '22 20:09

ceklock


You should use your LimitedTextField instead of TextField.

Replace this line:

final TextField t_fname = new TextField();

with this one:

final LimitedTextField t_fname = new LimitedTextField(maxLength);
like image 39
Julien Bodin Avatar answered Sep 23 '22 20:09

Julien Bodin