1

How would one limit the input of text into a TextField to where the only valid characters are numbers and letters? I've seen plenty of answers, and I tried one of them, but for some reason, I can't use backspace. The class is below.

private class NoSpaceField extends TextField {

        public void replaceText(int start, int end, String text) {
            String old = getText();
            if (text.matches("[A-Za-z0-9\b]")) {
                super.replaceText(start, end, text);
            }
            if (getText().length() > 16)
                setText(old);
            positionCaret(getText().length());
        }

        public void replaceSelection(String text) {
            String old = getText();
            if (text.matches("[A-Za-z0-9\b]")) {
                super.replaceSelection(text);
            }
            if (getText().length() > 16)
                setText(old);
            positionCaret(getText().length());
        }
    }

I am terrible at RegEx, and have no idea how to add backspace as a valid character. Also, I've used the above class (slightly modified) for a different purpose, and it works fine.

Tyler Senter
  • 137
  • 1
  • 13
  • Have you seen this thread, http://stackoverflow.com/questions/17438100/whats-the-use-of-the-b-backspace-regex – chris85 Mar 16 '15 at 02:25
  • @chris85 I tried `[A-Za-z0-9\b]`, but that didn't do anything, and increasing the number of backslashes just threw a PatternSyntaxException or didn't do anything. – Tyler Senter Mar 16 '15 at 02:29

3 Answers3

1

If you are on Java 8u40 you can use a TextFormatter, i. e. a filter like this:

TextField textField = new TextField();

TextFormatter<String> formatter = new TextFormatter<String>( change -> {
    change.setText(change.getText().replaceAll("[^a-zA-Z0-9]", ""));
    return change; 

});
textField.setTextFormatter(formatter);

This also solves the problem when you e. g. paste some invalid text into the textfield.

If you are on a lower jdk, then you may want to try RestrictiveTextField by Christian Schudt. Allows you to limit the characters and still use cursor keys, backspace, etc.

Roland
  • 18,114
  • 12
  • 62
  • 93
  • Interesting; I haven't seen this yet. Also, is there a way to limit the number of characters that can be entered? – Tyler Senter Mar 16 '15 at 20:43
  • Check the length of the change text in the text formatter's handler and modify it if the text is too long. However, using an additional ChangeListener for the limitation of the number of characters may be easier to implement. – Roland Mar 17 '15 at 01:43
0

\b is the ascii code for a backspace character. You can use this in your regex.

text.matches("[A-Za-z0-9\b]")

should do the trick

James
  • 903
  • 7
  • 22
  • I've tried that, but I still doesn't work; I don't know why. I haven't added any EventHandlers anywhere, but I can't use backspace at all. The only way to remove characters is to select several and use another character. – Tyler Senter Mar 16 '15 at 02:34
  • What tests have you run, and what output do you get? It's possible that the problem does not lie in the regex. Is the method replaceText being called every time a character is changed? Are the results possibly being overwritten elsewhere in your code? – James Mar 16 '15 at 02:36
  • The full class can be found [here](https://gist.github.com/ZonalYewHD/bc09767c0e9820d86010#file-setup-java-L124). I'm just using Eclipse to run the main method, and I test by entering text into the `Username` box in the application. – Tyler Senter Mar 16 '15 at 02:41
  • It looks like you are calling a new NoSpaceField object but not using the methods you've included to restrict the users text, or at least I cannot see this anywhere in the provided class. – James Mar 16 '15 at 02:44
  • JavaFX uses those methods when handling input. I've done the exact same thing in another, smaller program, and it works fine. – Tyler Senter Mar 16 '15 at 02:48
  • Consider contrasting the two programs to find the major differences if you must. Have you verified that your regex works and is restricting too only alphanumeric characters? – James Mar 16 '15 at 02:51
  • I've already looked, and there's no differences between them. However, you may find something I missed, so the class, and where it's used, are [here](https://gist.github.com/ZonalYewHD/c85795735fc9808f357c) and [here](https://gist.github.com/ZonalYewHD/86f347dfd6acb023ffc5). – Tyler Senter Mar 16 '15 at 02:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/73046/discussion-between-zonalyewhd-and-james). – Tyler Senter Mar 16 '15 at 02:56
0

Deleting characters is performed by calling replaceText with an empty string and the indexes representing the character position(s) to be deleted. Since your regular expression doesn't match an empty string, the deletion is ignored.

What you probably want is to accept "zero or more" valid characters. That way you will recognize an empty string, as well as supporting copy-and-paste for multiple characters. The regex for this looks like

private class NoSpaceField extends TextField {

    public void replaceText(int start, int end, String text) {
        String old = getText();
        if (text.matches("[A-Za-z0-9]*")) {
            super.replaceText(start, end, text);
        }
        if (getText().length() > 16)
            setText(old);
        positionCaret(getText().length());
    }

    public void replaceSelection(String text) {
        String old = getText();
        if (text.matches("[A-Za-z0-9]*")) {
            super.replaceSelection(text);
        }
        if (getText().length() > 16)
            setText(old);
        positionCaret(getText().length());
    }
}
James_D
  • 201,275
  • 16
  • 291
  • 322