1

How can I restrict the input from the user to only hexadecimal values? With decimal notation the range is from 0 to 16383, but I would like to let the user type an hexadecimal number into TextField. Therefore the range should be from 0x0000 to 0x3FFF. I have already built my GUI via SceneBuilder, therefore I just need a function to handle restriction and conversion on user's input.

EDIT

This is my version:

startAddressField.textProperty().addListener((observable, oldValue, newValue) -> {
        if (!newValue.matches("^[0-9A-F]?")) {
            startAddressField.setText(oldValue);
        }
    });
2
  • 3
    What have you tried already? Post your code that way we can help you figure out where you are going wrong. You can set a TextFormatter on the field to monitor and restrict entry. Commented Jul 5, 2018 at 13:45
  • Hint : You are probably going to need a customer editor on the field Commented Jul 5, 2018 at 14:12

3 Answers 3

4

Use a TextFormatter with UnaryOperator and StringConverter<Integer> as shown below:

UnaryOperator<TextFormatter.Change> filter = change -> change.getControlNewText().matches("[0-3]?\\p{XDigit}{0,3}") ? change : null;

StringConverter<Integer> converter = new StringConverter<Integer>() {

    @Override
    public String toString(Integer object) {
        return object == null ? "" : Integer.toHexString(object);
    }

    @Override
    public Integer fromString(String string) {
        return string == null || string.isEmpty() ? null : Integer.parseInt(string, 16);
    }

};

TextFormatter<Integer> formatter = new TextFormatter<>(converter, null, filter);
textField.setTextFormatter(formatter);

The converted value is available via TextFormatter.value property. It only gets updated on pressing enter or the TextField loosing focus.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks I am trying your solution and it seems working good. however I encounter an error: how can I overcome the illegal escape character in "[0-3]?\p{XDigit}{0,3}"? I am trying with a double backslash!
1


best way to do it is with regular expressions:

yourTextField.textProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> observable, String oldValue,
                            String newValue) {
            if (!newValue.matches("^[0-9A-F]+$")) {
                yourTextField.setText(newValue.replaceAll("[^\\d]", ""));
            }
        }
    });

Is this what your are looking for?

3 Comments

Thanks for your answer, I did something similar too, you can see it in the edit. However, I was thinking about a way to implement the range limitation and the Integer conversion.
You should non, hexadecimal values, not just non-digit values (for those \D could be used btw). Otherwise 3AC! results in 3 not in 3AC.
no, don't listen and revert - instead use a TextFormatter as @fabian explained in his accepted (!) answer
1

An idea may be to parse it into integer format first. You can use:

int value = Integer.decode("your hex value here");

if the string is not a proper value, it will throw a number format exception, however the decode function will also work for any valid integer (so something base 10 will work as well in this case).

An alternative you could try is:

int value = Integer.parseInt("hex value",16)

However for this method you will need to get rid of the "0x" header from your String

Since you are performing a check, surround it with a try catch block and whatever is caught would be an improperly formatted hex.

Furthermore if you need to check whether the value is between 0 to 16383, just use the value returned by the methods above.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.