JavaFX中如何将TableView选中行数据传递至修改场景文本框
JavaFX场景间传递选中Part实例解决空指针问题
问题根源
你之前尝试让修改零件控制器继承主控制器,想在initialize()里通过partTableView.getSelectionModel()拿选中项,但这完全行不通——不同场景的控制器是独立的实例,继承并不能共享主控制器的UI组件引用,所以修改控制器里的partTableView必然是null,触发空指针异常。本质问题是没把主页面选中的Part实例直接传递到修改场景,反而试图跨场景获取UI元素。
解决方案
1. 重构控制器结构,取消继承关系
修改零件控制器和主控制器是平级的,各自管各自的UI,没必要继承。修改控制器可以实现Initializable,但初始化逻辑里别碰主控制器的元素。
2. 在修改控制器里加接收Part的方法
给修改控制器加一个方法,专门接收从主控制器传过来的选中Part,然后把数据填充到文本框里:
public class ModifyPartController implements Initializable { @FXML private TextField nameField; @FXML private TextField costField; @FXML private TextField stockField; @FXML private TextField minField; @FXML private TextField maxField; private Part selectedPart; // 接收主页面传递的选中零件 public void setSelectedPart(Part part) { this.selectedPart = part; // 把零件数据填充到对应文本框 nameField.setText(part.getName()); costField.setText(String.valueOf(part.getCost())); stockField.setText(String.valueOf(part.getStock())); minField.setText(String.valueOf(part.getMin())); maxField.setText(String.valueOf(part.getMax())); } @Override public void initialize(URL url, ResourceBundle resourceBundle) { // 这里搞点通用初始化,比如文本框输入校验,别碰主控制器的东西 } }
3. 主控制器处理修改按钮点击,传递选中Part
在主控制器的修改按钮事件里,先拿到选中的Part,再加载修改场景,获取修改控制器实例,调用刚才的方法把Part传过去:
public class MainController { @FXML private TableView<Part> partTableView; @FXML private ObservableList<Part> partsList; // 绑定TableView的数据源 @FXML private void onModifyPartClicked(ActionEvent event) { Part selectedPart = partTableView.getSelectionModel().getSelectedItem(); if (selectedPart == null) { // 提示用户先选零件 Alert alert = new Alert(Alert.AlertType.WARNING); alert.setTitle("提示"); alert.setHeaderText(null); alert.setContentText("请先选择要修改的零件"); alert.showAndWait(); return; } try { // 加载修改场景的FXML FXMLLoader loader = new FXMLLoader(getClass().getResource("modify-part.fxml")); Parent root = loader.load(); // 获取修改控制器实例 ModifyPartController modifyController = loader.getController(); // 传递选中的零件 modifyController.setSelectedPart(selectedPart); // 切换到修改场景 Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); stage.setScene(new Scene(root)); stage.show(); } catch (IOException e) { e.printStackTrace(); } } }
4. 修改完成后更新数据源
在修改控制器的保存按钮事件里,把文本框的新值更新到selectedPart上。如果你的Part类用了JavaFX的可观察属性(比如SimpleStringProperty、SimpleDoubleProperty),那ObservableList绑定的TableView会自动刷新;如果Part是普通POJO,就手动找到它在列表里的位置替换:
@FXML private void onSaveModifyClicked(ActionEvent event) { // 从文本框取新值 String name = nameField.getText(); double cost = Double.parseDouble(costField.getText()); int stock = Integer.parseInt(stockField.getText()); int min = Integer.parseInt(minField.getText()); int max = Integer.parseInt(maxField.getText()); // 更新选中零件的属性 selectedPart.setName(name); selectedPart.setCost(cost); selectedPart.setStock(stock); selectedPart.setMin(min); selectedPart.setMax(max); // 要是Part是普通POJO,就手动刷新列表: // int index = partsList.indexOf(selectedPart); // partsList.set(index, selectedPart); // 返回主页面 Stage stage = (Stage) ((Node) event.getSource()).getScene().getWindow(); stage.close(); }
内容的提问来源于stack exchange,提问作者Anthony Collins
相关产品推荐
相关产品推荐

