JFormattedTextField与NumberFormatter、DecimalFormat的异常行为排查
解决方案
要实现输入123456自动转换为1234.5,同时限制数值范围在-9999.9到9999.9之间,需要调整NumberFormatter的配置并自定义解析逻辑,以下是修正后的代码:
import java.awt.*; import javax.swing.*; import javax.swing.text.*; import java.text.*; public class testwindow extends JPanel { private JFormattedTextField field1; public testwindow() { try { DecimalFormat decimalFormat = new DecimalFormat("#0.0;-#0.0"); decimalFormat.setMinimumIntegerDigits(1); decimalFormat.setMaximumIntegerDigits(4); decimalFormat.setMinimumFractionDigits(1); decimalFormat.setMaximumFractionDigits(1); // 自定义NumberFormatter,处理输入过长的情况 NumberFormatter realFormatter = new NumberFormatter(decimalFormat) { @Override public Object parseObject(String text) throws ParseException { // 移除负号,单独处理数字部分 String numText = text.replace("-", ""); if (numText.length() > 5) { // 4位整数+1位小数,共5位有效长度 // 截取前4位作为整数部分,第5位作为小数部分 String integerPart = numText.substring(0, 4); String fractionPart = numText.substring(4, 5); numText = integerPart + "." + fractionPart; // 还原负号 if (text.startsWith("-")) { numText = "-" + numText; } } // 解析处理后的字符串 Number num = (Number) super.parseObject(numText); // 强制数值在设定范围内 double value = num.doubleValue(); if (value > 9999.9) { return 9999.9; } else if (value < -9999.9) { return -9999.9; } return num; } }; realFormatter.setOverwriteMode(true); realFormatter.setAllowsInvalid(false); // 设置数值上下限,防止解析后超出范围 realFormatter.setMinimum(-9999.9); realFormatter.setMaximum(9999.9); // 使用Double类型避免float精度丢失问题 realFormatter.setValueClass(Double.class); field1 = new JFormattedTextField(realFormatter); field1.setValue(0.0); setPreferredSize(new Dimension(215, 30)); setLayout(new GridLayout(1, 1)); add(field1); } catch (Exception ex) { ex.printStackTrace(); } } public static void main(String[] args) { JFrame frame = new JFrame("MyPanel"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().add(new testwindow()); frame.pack(); frame.setVisible(true); } }
关键调整说明
- 自定义解析逻辑:重写
parseObject方法,当输入数字长度超过5位时,自动拆分整数和小数部分,确保输入123456转换为1234.5。 - 数值范围限制:通过
setMinimum和setMaximum强制最终值在-9999.9到9999.9区间内,避免超出范围的异常数值。 - 替换数值类型:用
Double替代原有的Float,解决浮点数精度丢失导致的异常显示(如之前的4050.6问题)。 - 保留覆盖模式:保持
setOverwriteMode(true),确保输入时逐位覆盖现有内容,符合预期的输入体验。
解决的原问题
- 输入
123456时自动转换为1234.5,而非异常数值。 - 修复了仅绑定
DecimalFormat时负号只能在首位输入的问题,通过NumberFormatter统一处理正负号。 - 解决了多次输入9仅增加0.1的问题,自定义解析确保输入的数字正确整合到数值中。
内容的提问来源于stack exchange,提问作者kcswalter
相关产品推荐
相关产品推荐

