JavaFX:点击按钮时如何从TableView获取筛选后的值
JavaFX筛选TableView后获取值并跳转FXML问题
我是JavaFX新手,正在尝试用TextField实现带筛选功能的TableView。设置了TextField和搜索按钮,需求是在TextField输入搜索值后点击搜索按钮,若该值存在于表格中,需加载另一个FXML(将选中值作为参数传递给该FXML及其控制器),但无法在handleSearch()方法中获取筛选后的值。
FXML代码
<TableView fx:id="mTableView" layoutY="71.0" prefHeight="451.0" prefWidth="929.0" GridPane.rowIndex="1"> <columns> <TableColumn fx:id="idColumn" prefWidth="75.0" text="ID" /> <TableColumn fx:id="nameColumn" prefWidth="75.0" text="Name" /> <TableColumn fx:id="salColumn" prefWidth="75.0" text="Salary" /> </columns> </TableView> .... .... <TextField fx:id="mTextField" prefHeight="28.0" prefWidth="366.0" /> <Button fx:id="searchBtn" mnemonicParsing="false" onAction="#handleSearch" prefHeight="26.0" prefWidth="166.0" text="Search" />
控制器代码
@FXML private TableView<Employee> mTableView; @FXML private TableColumn<Employee, Integer> idColumn; @FXML private TableColumn<Employee, String> nameColumn; @FXML private TableColumn<Employee, String> salColumn; ObservableList<Employee> mList = FXCollections.observableArrayList(); @FXML public void handleSearch(ActionEvent event) { // 需要在这里获取筛选后的值以加载另一个fxml } public void loadRecords(){ // 此方法用于从数据库加载数据填充TableView(从控制器的initialize()方法调用) ... ... idColumn.setCellValueFactory(new PropertyValueFactory<>("id")); nameColumn.setCellValueFactory(new PropertyValueFactory<>("Name")); salColumn.setCellValueFactory(new PropertyValueFactory<>("salary")); mTableView.setItems(mList); FilteredList<Employee> filteredList = new FilteredList<>(mList,b->true); mTextField.textProperty().addListener(((observableValue, oldValue, newValue) -> { key = null; filteredList.setPredicate(cinema -> { if(newValue.isEmpty() || newValue.isBlank() || newValue == null){ return true; } String searchKeyword = newValue.toLowerCase(); if(isContain(cinema.getId().toString().toLowerCase(),searchKeyword)){ return true; } else { return false; } }); })); SortedList<Employee> sortedList = new SortedList<>(filteredList); key = filteredList.get(0).getId().toString(); sortedList.comparatorProperty().bind(mTableView.comparatorProperty()); mTableView.setItems(sortedList); }
解决方案
1. 将FilteredList改为成员变量
目前FilteredList是loadRecords()方法的局部变量,handleSearch()无法访问。把它提升为控制器的成员变量,并补充TextField的FXML注入:
@FXML private TextField mTextField; private FilteredList<Employee> filteredList; // 成员变量
然后在loadRecords()里初始化:
filteredList = new FilteredList<>(mList, b->true);
2. 在handleSearch()中获取筛选结果
有两种实用方式:
- 方式一:获取用户选中的项(支持多结果场景下用户自主选择)
@FXML public void handleSearch(ActionEvent event) { Employee selectedEmployee = mTableView.getSelectionModel().getSelectedItem(); if(selectedEmployee != null){ // 加载另一个FXML并传递参数 loadAnotherFXML(selectedEmployee); } else { // 提示用户先选择项 Alert alert = new Alert(Alert.AlertType.WARNING); alert.setTitle("提示"); alert.setHeaderText(null); alert.setContentText("请先选择表格中的员工"); alert.showAndWait(); } }
- 方式二:直接获取筛选后的第一个匹配项(适合确定唯一匹配的场景)
@FXML public void handleSearch(ActionEvent event) { if(!filteredList.isEmpty()){ Employee matchedEmployee = filteredList.get(0); loadAnotherFXML(matchedEmployee); } else { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle("提示"); alert.setHeaderText(null); alert.setContentText("没有找到匹配的员工"); alert.showAndWait(); } }
3. 实现加载另一个FXML并传递参数
private void loadAnotherFXML(Employee employee) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource("目标FXML文件路径.fxml")); Parent root = loader.load(); // 获取目标控制器并传递参数 AnotherController controller = loader.getController(); controller.setEmployee(employee); // 假设目标控制器有对应的参数接收方法 // 切换场景(也可改为弹出新窗口) Stage stage = (Stage) mTableView.getScene().getWindow(); stage.setScene(new Scene(root)); stage.show(); } catch (IOException e) { e.printStackTrace(); } }
4. 额外优化提示
- 确保
Employee类的属性名与PropertyValueFactory参数对应(比如nameColumn用的"Name"要对应Employee类的getName()方法,或使用JavaFX属性) - 避免在
loadRecords()中直接调用filteredList.get(0),若初始列表为空会报错,建议添加非空判断
内容的提问来源于stack exchange,提问作者Akhil
相关产品推荐
相关产品推荐

