本教程详细讲解如何在javafx应用中实现tableview的数据筛选功能,并通过文本输入框和按钮交互,动态获取筛选后的数据。文章将涵盖filteredlist和sortedlist的使用、文本监听器实现实时筛选,以及在按钮点击事件中准确获取当前tableview中显示的数据项,并探讨如何将这些数据传递给其他fxml视图进行进一步处理。
在JavaFX应用程序中,TableView 是一个功能强大的组件,常用于展示大量结构化数据。当数据量较大时,提供搜索和筛选功能可以极大地提升用户体验。本教程将指导您如何结合 TextField 和 Button,实现对 TableView 数据的动态筛选,并在用户点击搜索按钮后,获取并处理筛选后的结果。
JavaFX提供了一套灵活的机制来管理和筛选 TableView 的数据。主要涉及到以下几个关键类:
通过将 FilteredList 绑定到 TextField 的文本变化监听器上,我们可以实现实时搜索功能。
首先,我们需要一个包含 TableView、TextField 和 Button 的FXML布局文件。
接下来,是对应的控制器骨架和数据模型。
package com.example;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.function.Predicate;
public class TableController implements Initializable {
@FXML
private TableView mTableView;
@FXML
private TableColumn idColumn;
@FXML
private TableColumn nameColumn;
@FXML
private TableColumn salColumn; // 假设Salary是Double类型
@FXML
private TextField mTextField;
@FXML
private Button searchBtn;
private ObservableList mList = FXCollections.observableArrayList();
private FilteredList filteredList;
private SortedList sortedList;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// 初始化列的单元格值工厂
idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
salColumn.setCellValueFactory(new PropertyValueFactory<>("salary"));
// 模拟加载数据
loadRecords();
// 初始化FilteredList和SortedList
filteredList = new FilteredList<>(mList, b -> true); // 初始显示所有数据
sortedList = new SortedList<>(filteredList);
sortedList.comparatorProperty().bind(mTableView.comparatorProperty()); // 绑定排序属性
mTableView.setItems(sortedList); // 将排序列表设置给TableView
// 添加TextField的文本变化监听器,实现实时筛选
mTextField.textProperty().addListener((observable, oldValue, newValue) -> {
filteredList.setPredicate(createSearchPredicate(newValue));
});
}
/**
* 模拟从数据库或其他源加载数据
*/
private void loadRecords() {
mList.add(new Employee(101, "Alice", 5000.0));
mList.add(new Employee(102, "Bob", 6000.0));
mList.add(new Employee(103, "Charlie", 7500.0));
mList.add(new Employee(104, "David", 4500.0));
mList.add(new Employee(201, "Eve", 8000.0));
mList.add(new Employee(202, "Frank", 9000.0));
}
/**
* 根据搜索关键字创建Predicate
* @param searchText 搜索文本
* @return Predicate
*/
private Predicate createSearchPredicate(String searchText) {
return employee -> {
// 如果搜索文本为空,显示所有数据
if (searchText
== null || searchText.isEmpty() || searchText.isBlank()) {
return true;
}
String lowerCaseSearchText = searchText.toLowerCase();
// 检查员工ID是否包含搜索关键字
if (String.valueOf(employee.getId()).toLowerCase().contains(lowerCaseSearchText)) {
return true;
}
// 检查员工姓名是否包含搜索关键字
if (employee.getName().toLowerCase().contains(lowerCaseSearchText)) {
return true;
}
// 可以添加更多字段的检查,例如薪水
// if (String.valueOf(employee.getSalary()).toLowerCase().contains(lowerCaseSearchText)) {
// return true;
// }
return false; // 不匹配
};
}
@FXML
public void handleSearch(ActionEvent event) {
// 此方法将在下面详细实现
}
} Employee数据模型:
package com.example;
import javafx.beans.property.*;
public class Employee {
private final IntegerProperty id;
private final StringProperty name;
private final DoubleProperty salary;
public Employee(int id, String name, double salary) {
this.id = new SimpleIntegerProperty(id);
this.name = new SimpleStringProperty(name);
this.salary = new SimpleDoubleProperty(salary);
}
public int getId() {
return id.get();
}
public IntegerProperty idProperty() {
return id;
}
public void setId(int id) {
this.id.set(id);
}
public String getName() {
return name.get();
}
public StringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public double getSalary() {
return salary.get();
}
public DoubleProperty salaryProperty() {
return salary;
}
public void setSalary(double salary) {
this.salary.set(salary);
}
}当用户在 TextField 中输入搜索词并点击“搜索”按钮时,我们通常希望获取当前 TableView 中显示(即已经过筛选和排序)的数据。
关键在于 mTableView.getItems() 方法。无论 TableView 绑定的是原始 ObservableList、FilteredList 还是 SortedList,mTableView.getItems() 总是返回当前 TableView 实际显示的数据列表。因此,如果您的 TableView 已经绑定了 SortedList(它又包装了 FilteredList),那么 getItems() 返回的就是经过筛选和排序后的数据。
在 handleSearch 方法中,您可以这样获取数据:
@FXML
public void handleSearch(ActionEvent event) {
// 获取当前TableView中显示的所有数据项
ObservableList currentDisplayedEmployees = mTableView.getItems();
if (currentDisplayedEmployees.isEmpty()) {
System.out.println("没有找到匹配的员工。");
// 可以显示一个提示信息给用户
// Alert alert = new Alert(Alert.AlertType.INFORMATION, "没有找到匹配的员工!");
// alert.showAndWait();
} else {
// 假设我们只关心第一个匹配项
Employee firstResult = currentDisplayedEmployees.get(0);
System.out.println("搜索结果的第一个员工ID: " + firstResult.getId() + ", 姓名: " + firstResult.getName());
// 如果需要,您可以遍历所有结果
// for (Employee emp : currentDisplayedEmployees) {
// System.out.println("匹配员工: " + emp.getName());
// }
// 进一步处理:例如,加载另一个FXML并传递这个员工对象
// loadAnotherFxml(firstResult);
}
} 在实际应用中,您可能需要将筛选出的数据(例如 firstResult)传递给另一个FXML视图的控制器。这通常通过 FXMLLoader 来实现。
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
// ... 在TableController中 ...
private void loadAnotherFxml(Employee employeeToPass) {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/example/detailView.fxml"));
Parent root = loader.load();
// 获取目标控制器的实例
DetailController detailController = loader.getController();
// 调用目标控制器的方法来设置数据
detailController.initData(employeeToPass);
Stage stage = new Stage();
stage.setScene(new Scene(root));
stage.setTitle("员工详情");
stage.show();
// 如果需要关闭当前窗口
// ((Stage) mTableView.getScene().getWindow()).close();
} catch (IOException e) {
e.printStackTrace();
// 错误处理,例如显示一个警告框
// Alert alert = new Alert(Alert.AlertType.ERROR, "无法加载详情视图:" + e.getMessage());
// alert.showAndWait();
}
}对应的 DetailController 示例:
package com.example;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class DetailController {
@FXML
private Label idLabel;
@FXML
private Label nameLabel;
@FXML
private Label salaryLabel;
public void initData(Employee employee) {
if (employee != null) {
idLabel.setText("ID: " + employee.getId());
nameLabel.setText("姓名: " + employee.getName());
salaryLabel.setText("薪水: " + employee.getSalary());
}
}
}以及 detailView.fxml 示例:
通过本教程,您应该已经掌握了如何在JavaFX中实现 TableView 的动态筛选功能。核心在于利用 FilteredList 和 SortedList 来管理数据视图,并通过 TextField 的文本监听器实时更新筛选条件。在按钮点击事件中,mTableView.getItems() 方法是获取当前筛选后数据集合的关键。结合 FXMLLoader,您可以轻松地将这些数据传递到其他视图,构建更加复杂和交互性强的JavaFX应用程序。