为何filterInput在特定场景下会接收带标点的格式化数字?
JavaFX文本框赋值时出现千分位格式化导致校验失败的问题分析与解决
问题原因
这事儿的核心在于**IntegerStringConverter的默认行为**:它会根据当前系统的区域设置对数字进行格式化,自动添加千分位分隔符(比如把1234转成1,234)。
为什么之前有初始默认值时没问题?那是因为视图启动时的初始值设置流程可能跳过了输入过滤器的校验;但当你把模型默认值改成0后,后续给someInteger赋值时,转换器会先把数值格式化为带逗号的字符串,再推送到文本框——而你的filterInput规则是检查controlNewText是否为纯整数,带逗号的字符串自然通不过校验,导致新值被拦截,文本框无法更新。
解决方案
有两种思路可以彻底解决这个问题,按需选择:
1. 自定义无格式化的Integer转换器(推荐)
直接替换掉默认的IntegerStringConverter,实现一个只返回纯数字字符串的转换器,从根源上避免格式化带来的逗号:
class PlainIntegerStringConverter : IntegerStringConverter() { override fun toString(value: Int?): String { // 直接返回整数的字符串形式,不带任何格式 return value?.toString() ?: "" } }
然后修改文本框的TextFormatter配置:
textfield(model.someInteger) { required() textFormatter = TextFormatter(PlainIntegerStringConverter(), model.item.someInteger) stripNonInteger() filterInput { it.controlNewText.isInt() } }
这样模型推送数值时,转换器只会输出纯数字字符串,输入过滤器的校验就能正常通过了。
2. 修改输入过滤器的校验逻辑
如果不想自定义转换器,也可以调整filterInput的规则,先清除所有非数字字符再检查是否为整数:
filterInput { // 移除所有非数字和负号的字符(如果需要支持负数的话) val cleanedText = it.controlNewText.replace(Regex("[^\\d-]"), "") cleanedText.isInt() }
这种方法兼容带逗号的格式化字符串,不过需要注意如果你的业务不允许负数,可以去掉正则里的-。
额外提醒
还要确认你的stripNonInteger()扩展函数的执行顺序,确保它在filterInput之前处理文本,不过第一种自定义转换器的方法更直接,能避免这类顺序问题。
内容的提问来源于stack exchange,提问作者Carlton Whitehead
相关产品推荐
相关产品推荐

