0

I'm creating a custom TextArea which accepts negative decimals while the user is writing.

This is what I found online for decimal TextAreas

public DecimalTextField() {

    super();

    UnaryOperator<Change> filter = new UnaryOperator<TextFormatter.Change>() {

        @Override
        public TextFormatter.Change apply(TextFormatter.Change t) {

            if (t.isReplaced()) 
                if(t.getText().matches("[^0-9]"))
                    t.setText(t.getControlText().substring(t.getRangeStart(), t.getRangeEnd()));


            if (t.isAdded()) {
                if (t.getControlText().contains(".")) {
                    if (t.getText().matches("[^0-9]")) {
                        t.setText("");
                    }
                } else if (t.getText().matches("[^0-9.]")) {
                    t.setText("");
                }
            }

            return t;
        }
    };

    this.setTextFormatter(new TextFormatter<>(filter));

}

Now I need it to accept a "-" in the beginning but I think it's not as simple as it seems.

AwesomeGuy
  • 537
  • 1
  • 6
  • 17

1 Answers1

1

Using this answer, create a custom StringConverter<Double> and use it with a UnaryOperator<TextFormatter.Change> to accept only double numbers:

NumberFormat numberFormat = NumberFormat.getNumberInstance(); // you can set a locale here
UnaryOperator<TextFormatter.Change> filter = change -> {
    String controlNewText = change.getControlNewText();
    if ("-".equals(controlNewText)) {
        return change;
    } else {
        try {
            numberFormat.parse(controlNewText);
            return change;
        } catch (ParseException | NullPointerException ignored) {
            return null;
        }
    }
};
StringConverter<Double> converter = new StringConverter<Double>() {
    @Override
    public Double fromString(String s) {
        try {
            return numberFormat.parse(s).doubleValue();
        } catch (ParseException ignored) {
            return 0.0;
        }
    }
    @Override
    public String toString(Double d) {
        return numberFormat.format(d);
    }
};
this.setTextFormatter(new TextFormatter<>(converter, 0.0, filter));

UPDATE: The answer was update to use NumberFormat instead of regex Pattern to avoid problems happens when different Locale is used.

Miss Chanandler Bong
  • 4,081
  • 10
  • 26
  • 36
  • 1
    better not use manual pattern matching - that will break with different Locales. Instead, use an appropriate NumberFormat – kleopatra Feb 05 '20 at 13:17
  • @kleopatra, you're right. That implementation might cause problems when used with different locales. I updated my answer to use `NumberFormat`. Thanks for the note. – Miss Chanandler Bong Feb 07 '20 at 10:04