JavaFX TextFormatter整数范围验证问题:TableView下限校验失效
JavaFX TableView 整数输入范围校验(100-500)修复方案
你的代码核心问题是输入过程中的中间值被直接拦截:比如用户输入"1"时,数值1小于100会被直接拒绝,导致根本无法输入完整的"100"。当前逻辑要求每一步输入后的数值都必须在100-500之间,但实际输入是逐步完成的,需要允许合法的中间输入,最终只限制完整数值在范围内。
修正后的校验逻辑
private static final int MIN_RANGE_VALUE = 100; private static final int MAX_RANGE_VALUE = 500; UnaryOperator<Change> flowFilter = change -> { String newText = change.getControlNewText(); // 允许空输入,方便用户删除内容 if (newText.isEmpty()) { return change; } // 只允许输入纯数字,过滤非数字字符 if (!newText.matches("\\d+")) { return null; } try { int value = Integer.parseInt(newText); // 完整数值在范围内,直接允许 if (value >= MIN_RANGE_VALUE && value <= MAX_RANGE_VALUE) { return change; } else { // 处理输入过程中的中间值:判断是否有可能扩展成合法数值 if (newText.length() < 3) { // 长度为1时,只能是1-5(只有1xx到5xx才可能落在范围内) if (newText.length() == 1) { char firstChar = newText.charAt(0); return (firstChar >= '1' && firstChar <= '5') ? change : null; } // 长度为2时,允许10-50(10可扩展为100+,50可扩展为500;51+扩展后超上限,0-9扩展后不足下限) else if (newText.length() == 2) { int twoDigitVal = Integer.parseInt(newText); return (twoDigitVal >= 10 && twoDigitVal <= 50) ? change : null; } } // 长度≥3且不在范围内,直接拒绝 return null; } } catch (NumberFormatException e) { // 已通过\\d+校验,理论不会触发 return null; } };
逻辑要点说明
- 允许空输入:用户可以自由删除单元格内容
- 过滤非数字:确保只能输入整数类型
- 中间值判断:
- 单数字只允许1-5,避免输入0、6-9这类无法扩展成合法数值的字符
- 两位数允许10-50,既保证可以扩展为100-500,又拦截51-99(扩展后超上限)、0-9(扩展后不足下限)的无效输入
- 三位数直接校验是否在100-500范围内,不符合则拒绝
单元格应用示例
将校验逻辑绑定到TableView可编辑单元格的示例代码:
TableColumn<YourDataModel, Integer> numberColumn = new TableColumn<>("数值列"); numberColumn.setCellValueFactory(new PropertyValueFactory<>("numberProperty")); numberColumn.setCellFactory(col -> new TableCell<YourDataModel, Integer>() { private final TextField textField = new TextField(); private final TextFormatter<Integer> textFormatter; { // 绑定校验逻辑 textFormatter = new TextFormatter<>(new IntegerStringConverter(), null, flowFilter); textField.setTextFormatter(textFormatter); // 处理编辑提交 textField.setOnAction(e -> commitEdit(textFormatter.getValue())); textField.focusedProperty().addListener((obs, oldFocus, newFocus) -> { if (!newFocus) { commitEdit(textFormatter.getValue()); } }); } @Override protected void updateItem(Integer item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { setText(null); setGraphic(null); } else { if (isEditing()) { textField.setText(item.toString()); setGraphic(textField); setText(null); } else { setText(item.toString()); setGraphic(null); } } } @Override public void startEdit() { super.startEdit(); textField.setText(getItem().toString()); setGraphic(textField); setText(null); textField.requestFocus(); } @Override public void cancelEdit() { super.cancelEdit(); setText(getItem().toString()); setGraphic(null); } });
内容的提问来源于stack exchange,提问作者codekun
相关产品推荐
相关产品推荐

