具有货币值动态掩码的文本字段 JavaFX(使用 TextFormatter)

Textfield JavaFX with dynamic mask for monetary values (Using TextFormatter)

我正在使用 TextFomater 将我的 TextField 作为动态货币文本字段,使用以下代码:

  public class MoneyTextFieldOperator implements UnaryOperator<TextFormatter.Change>
{
    final char seperatorChar = '.';
    final Pattern p;
    int length;

    public MoneyTextFieldOperator(int length) {
        this.length=length;
        this.p = Pattern.compile("[0-9. ]*");
    }

    @Override
    public TextFormatter.Change apply(final TextFormatter.Change c) {
        if (c.isContentChange() && c.getControlNewText().length() > length) {
            return null;
        }
        else {
        if (!c.isContentChange()) {
            return c;
        }
        final String newText = c.getControlNewText();
        if (newText.isEmpty()) {
            return c;
        }
        if (!this.p.matcher(newText).matches()) {
            return null;
        }
        final int suffixCount = c.getControlText().length() - c.getRangeEnd();

        int digits = suffixCount - suffixCount / 4;

        final StringBuilder sb = new StringBuilder();
        if (digits % 3 == 0 && digits > 0 && suffixCount % 4 != 0) {
            sb.append('.');
        }
        for (int i = c.getRangeStart() + c.getText().length() - 1; i >= 0; --i) {

            final char letter = newText.charAt(i);
            if (Character.isDigit(letter)) {
                sb.append(letter);
                if (++digits % 3 == 0) {
                    System.out.println("digits   : "+digits);
                    sb.append('.');
                }
            }
        }
        if (digits % 3 == 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.reverse();
        final int length = sb.length();
        c.setRange(0, c.getRangeEnd());
        c.setText(sb.toString());
        c.setCaretPosition(length);
        c.setAnchor(length);
        return c;
    }}

并按如下方式调用它:

montantTextField.setTextFormatter(new TextFormatter(new MoneyTextFieldOperator(10)));

问题是它只对整数有效,我想让它现在对小数有效,所以当用户输入 254648,32 它将它转换为 254.648,32

这是一个使用数字格式的建议解决方案:

    public class MoneyTextFieldOperator implements UnaryOperator<TextFormatter.Change> {

Pattern p;
int length;

public MoneyTextFieldOperator(int length) {
    this.length = length;
    this.p = Pattern.compile("[0-9. ,]*");
}

@Override
public TextFormatter.Change apply(TextFormatter.Change c) {
    Pattern acceptedKeywords = Pattern.compile("[0-9 . ,]*");

    int wholeNumberLength = 9;
    int decimalPartLength = 2;

    String newText = c.getControlNewText();

    String wholeNumber;
    String decimalPart;

    if (newText.contains(",")) {
        wholeNumber = newText.substring(0, newText.indexOf(","));
        decimalPart = newText.substring(newText.indexOf(",") + 1, newText.length());
    } else {
        wholeNumber = newText;
        decimalPart = "";
    }

    Matcher matcher = acceptedKeywords.matcher(newText);
    boolean isMatchingWithAcceptedKeywords = matcher.matches();
    String letter = c.getText();

    if (newText.isEmpty()) {
        return c;
    } else if (!c.isContentChange()) {
        return c;
    } else if (countChar(c.getControlNewText(), ',') > 1) {
        return null;
    } else if (!isMatchingWithAcceptedKeywords) {
        return null;
    } else if (wholeNumber.replace(".", "").length() > wholeNumberLength || decimalPart.length() > decimalPartLength) {
        return null;
    } else if (c.getControlNewText().charAt(0)==',') {
        return null;
    }

    else {
        c.setRange(0, c.getControlText().length());
        if (newText.contains(",")) {
            c.setText(NumbersTools.getMonetaryFormat(Integer.parseInt(wholeNumber.replace(".", ""))) + "," + decimalPart);
        } else {
            c.setText(NumbersTools.getMonetaryFormat(Integer.parseInt(wholeNumber.replace(".", ""))));
        }

        c.setCaretPosition(c.getText().length());
        c.setAnchor(c.getText().length());

        return c;
    }

}

public int countChar(String string, char charactere) {
    int x = 0;
    for (int i = 0; i <= string.length() - 1; ++i) {
        if (string.charAt(i) == charactere) {
            ++x;
        }
    }
    return x;
}

然后按如下方式使用它:

  textField.setTextFormatter(new TextFormatter<Object>(new MoneyTextFieldOperator(10)));