JavaFX可编辑TextFieldTableCell整数输入异常处理咨询
解决JavaFX TableView编辑Integer类型时的NumberFormatException弹窗问题
问题根源
你遇到的核心问题是:NumberFormatException是在JavaFX内置的IntegerStringConverter转换阶段抛出的,这个异常根本没传到你写的onPretChange或onCantitateChange方法的try-catch块里。默认转换器在无法将字符串转为Integer时直接抛异常,而这个异常是在JavaFX处理单元格编辑提交的内部流程中触发的,还没走到你的事件处理逻辑,所以你的catch完全捕获不到。
解决方案:自定义转换器处理转换异常
我们需要自定义一个IntegerStringConverter,重写fromString方法来捕获转换异常,同时弹出错误提示,还可以额外验证输入是否为自然数(符合你的业务需求)。
步骤1:添加自定义转换器内部类
在你的ControllerAdmin类中新增一个内部类:
private class CustomIntegerStringConverter extends IntegerStringConverter { private final String errorMsg; public CustomIntegerStringConverter(String errorMsg) { this.errorMsg = errorMsg; } @Override public Integer fromString(String input) { // 处理空输入的情况 if (input == null || input.trim().isEmpty()) { showErrorAlert(errorMsg); return null; } try { Integer value = super.fromString(input.trim()); // 额外验证是否为自然数(大于等于0) if (value < 0) { showErrorAlert(errorMsg); return null; } return value; } catch (NumberFormatException e) { showErrorAlert(errorMsg); // 返回null让单元格保持原有值,避免无效数据进入业务逻辑 return null; } } private void showErrorAlert(String message) { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setTitle("Eroare"); alert.setHeaderText(null); alert.setContentText(message); DialogPane dialogPane = alert.getDialogPane(); dialogPane.getStylesheets().add(getClass().getResource("/cssDesign/myDialogs.css").toExternalForm()); dialogPane.getStyleClass().add("myDialog"); alert.showAndWait(); } }
步骤2:替换默认转换器
修改你的loadTables方法,用自定义转换器替代默认的IntegerStringConverter:
private void loadTables() { table.setItems(observableList); table.getSelectionModel().selectedItemProperty().addListener((observer, oldData, newData) -> showDetails(newData)); table.setEditable(true); // 给价格和数量列使用自定义转换器 colPret.setCellFactory(TextFieldTableCell.forTableColumn(new CustomIntegerStringConverter("Pretul trebuie sa fie un numar natural"))); colCantitate.setCellFactory(TextFieldTableCell.forTableColumn(new CustomIntegerStringConverter("Cantitatea trebuie sa fie un numar natural"))); }
步骤3:优化编辑提交事件处理
修改你的onPretChange和onCantitateChange方法,确保只有转换成功(新值不为null)时才更新数据,同时处理业务层的ValidationException:
// 修正参数类型为<Produs, Integer>,避免强制类型转换 public void onPretChange(TableColumn.CellEditEvent<Produs, Integer> cellEditEvent) { Integer newValue = cellEditEvent.getNewValue(); if (newValue != null) { // 使用getRowValue获取当前编辑的行数据,比getSelectedItem更可靠 Produs produs = cellEditEvent.getRowValue(); Integer oldValue = produs.getPret(); try { produs.setPret(newValue); service.updateProdus(produs); } catch (ValidationException e) { showAllert(e); // 更新失败时恢复原有值 produs.setPret(oldValue); table.refresh(); } } } public void onCantitateChange(TableColumn.CellEditEvent<Produs, Integer> cellEditEvent) { Integer newValue = cellEditEvent.getNewValue(); if (newValue != null) { Produs produs = cellEditEvent.getRowValue(); Integer oldValue = produs.getCantitate(); try { produs.setCantitate(newValue); service.updateProdus(produs); } catch (ValidationException e) { showAllert(e); // 更新失败时恢复原有值 produs.setCantitate(oldValue); table.refresh(); } } }
步骤4:检查FXML绑定
确保你的FXML文件中,对应的TableColumn已经正确绑定了onEditCommit事件:
<TableColumn fx:id="colPret" onEditCommit="#onPretChange" ... /> <TableColumn fx:id="colCantitate" onEditCommit="#onCantitateChange" ... />
关键说明
- 自定义转换器直接在转换阶段捕获异常并弹窗,用户输入非法内容时能立即得到反馈。
- 返回
null可以让单元格保持编辑前的原有值,避免无效数据进入你的业务逻辑。 - 使用
getRowValue()获取当前编辑的行数据,比依赖getSelectedItem()更稳定,因为编辑时选中状态可能发生变化。
内容的提问来源于stack exchange,提问作者Diana Marginean
相关产品推荐
相关产品推荐

