You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX用TextFormatter实现动态掩码货币TextField 适配小数格式化需求

支持小数的JavaFX货币输入框TextFormatter实现

原有实现仅处理整数部分的千位分隔,未区分整数/小数段,且正则不支持逗号作为小数分隔符,修改后可满足你需要的输入254648,32自动转换为254.648,32的需求。

核心修改点

  • 调整正则匹配规则,允许最多1个逗号作为小数分隔符,限制小数位最多2位
  • 拆分输入内容为整数段、小数段两部分,千位分隔符仅作用于整数段
  • 长度校验改为仅统计数字位数,避免分隔符占用长度配额

完整实现代码

public class MoneyTextFieldOperator implements UnaryOperator<TextFormatter.Change> {
    // 千位分隔符
    final char thousandSeparator = '.';
    // 小数分隔符
    final char decimalSeparator = ',';
    final Pattern p;
    // 最大数字长度(不含分隔符)
    int maxDigitLength;

    public MoneyTextFieldOperator(int maxDigitLength) {
        this.maxDigitLength = maxDigitLength;
        // 正则允许数字、千位分隔符、小数分隔符
        this.p = Pattern.compile("[0-9.,]*");
    }

    @Override
    public TextFormatter.Change apply(final TextFormatter.Change c) {
        if (!c.isContentChange()) {
            return c;
        }
        final String newText = c.getControlNewText();
        if (newText.isEmpty()) {
            return c;
        }
        // 拦截非法字符
        if (!this.p.matcher(newText).matches()) {
            return null;
        }
        // 统计纯数字长度,判断是否超过限制
        long digitCount = newText.chars().filter(Character::isDigit).count();
        if (digitCount > maxDigitLength) {
            return null;
        }

        // 拆分整数和小数部分
        String integerPart;
        String decimalPart = "";
        if (newText.contains(String.valueOf(decimalSeparator))) {
            int separatorIndex = newText.indexOf(decimalSeparator);
            integerPart = newText.substring(0, separatorIndex);
            // 小数部分最多保留2位
            decimalPart = newText.substring(separatorIndex + 1)
                    .replaceAll("[^0-9]", "")
                    .substring(0, Math.min(2, newText.substring(separatorIndex + 1).length()));
        } else {
            integerPart = newText;
        }

        // 过滤整数部分的非数字字符,准备格式化
        String pureInteger = integerPart.replaceAll("[^0-9]", "");
        StringBuilder formattedInteger = new StringBuilder();
        // 从右往左每3位加千位分隔符
        for (int i = pureInteger.length() - 1, count = 0; i >= 0; i--, count++) {
            if (count != 0 && count % 3 == 0) {
                formattedInteger.append(thousandSeparator);
            }
            formattedInteger.append(pureInteger.charAt(i));
        }
        formattedInteger.reverse();

        // 拼接最终结果
        String finalText = formattedInteger.toString();
        if (!decimalPart.isEmpty()) {
            finalText += decimalSeparator + decimalPart;
        }

        // 设置变更内容
        c.setRange(0, c.getControlText().length());
        c.setText(finalText);
        c.setCaretPosition(finalText.length());
        c.setAnchor(finalText.length());
        return c;
    }
}

调用方式

和原有调用逻辑完全一致:

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

效果说明

  • 整数部分自动按每3位用.作为千位分隔符格式化
  • 输入逗号后自动识别为小数分隔符,小数部分最多保留2位
  • 非法字符(除数字、逗号、点之外的字符)会被自动拦截
  • 长度限制仅统计数字位数,不会被分隔符占用配额

内容的提问来源于stack exchange,提问作者Youssef Idraiss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 21:48:04