
本教程详细阐述了如何在 javafx 中实现 tableview 的动态数据过滤功能,通过 textfield 实时更新显示内容。重点讲解了如何在用户点击按钮时,从已过滤的 tableview 中准确获取当前显示的数据(特别是第一个匹配项),并演示了如何将这些获取到的数据安全地传递给另一个 fxml 视图及其控制器,以实现复杂的应用交互逻辑。
在 JavaFX 应用开发中,TableView 是一个常用的组件,用于展示结构化数据。当数据量较大时,用户往往需要通过搜索或过滤功能来快速定位所需信息。本教程将指导您如何实现一个带有动态过滤功能的 TableView,并在用户点击按钮时,获取当前过滤结果中的数据,并将其传递给另一个 FXML 视图。
为了实现动态过滤和数据获取,我们将使用以下 JavaFX 组件和集合类:
首先,我们需要一个简单的数据模型来表示表格中的每一行。以 Employee 为例:
// Employee.java
public class Employee {
private final SimpleIntegerProperty id;
private final SimpleStringProperty name;
private final SimpleStringProperty salary;
public Employee(int id, String name, String salary) {
this.id = new SimpleIntegerProperty(id);
this.name = new SimpleStringProperty(name);
this.salary = new SimpleStringProperty(salary);
}
public int getId() {
return id.get();
}
public SimpleIntegerProperty idProperty() {
return id;
}
public void setId(int id) {
this.id.set(id);
}
public String getName() {
return name.get();
}
public SimpleStringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.set(name);
}
public String getSalary() {
return salary.get();
}
public SimpleStringProperty salaryProperty() {
return salary;
}
public void setSalary(String salary) {
this.salary.set(salary);
}
}在 FXML 文件中,我们需要定义 TableView、TextField 和 Button。确保为它们设置 fx:id 和 onAction 属性,以便在控制器中引用和处理事件。
立即学习“Java免费学习笔记(深入)”;
<!-- YourView.fxml -->
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.GridPane?>
<AnchorPane prefHeight="600.0" prefWidth="950.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="yourpackage.YourController">
<children>
<GridPane layoutX="14.0" layoutY="14.0" prefHeight="572.0" prefWidth="929.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints maxHeight="100.0" minHeight="10.0" prefHeight="50.0" vgrow="SOMETIMES" />
<RowConstraints maxHeight="500.0" minHeight="10.0" prefHeight="500.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<TableView fx:id="mTableView" 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>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<TextField fx:id="mTextField" layoutX="14.0" layoutY="11.0" prefHeight="28.0" prefWidth="366.0" promptText="Enter ID to search" />
<Button fx:id="searchBtn" layoutX="394.0" layoutY="12.0" mnemonicParsing="false" onAction="#handleSearch" prefHeight="26.0" prefWidth="166.0" text="Search" />
</children>
</AnchorPane>
</children>
</GridPane>
</children>
</AnchorPane>控制器是实现所有业务逻辑的地方。我们将在这里初始化 TableView、绑定数据、实现过滤逻辑以及处理按钮点击事件。
// YourController.java
package yourpackage;
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.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
public class YourController implements Initializable {
@FXML
private TableView<Employee> mTableView;
@FXML
private TableColumn<Employee, Integer> idColumn;
@FXML
private TableColumn<Employee, String> nameColumn;
@FXML
private TableColumn<Employee, String> salColumn;
@FXML
private TextField mTextField;
@FXML
private Button searchBtn;
private ObservableList<Employee> mList = FXCollections.observableArrayList();
private FilteredList<Employee> filteredList;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// 1. 初始化 TableColumn 的单元格值工厂
idColumn.setCellValueFactory(new PropertyValueFactory<>("id"));
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
salColumn.setCellValueFactory(new PropertyValueFactory<>("salary"));
// 2. 加载数据 (这里使用模拟数据,实际应用中可能从数据库加载)
loadRecords();
// 3. 创建 FilteredList 并绑定到原始数据
filteredList = new FilteredList<>(mList, b -> true); // b->true 表示默认显示所有数据
// 4. 为 TextField 添加监听器,实现动态过滤
mTextField.textProperty().addListener((observable, oldValue, newValue) -> {
filteredList.setPredicate(employee -> {
// 如果搜索框为空或空白,则显示所有数据
if (newValue == null || newValue.isEmpty() || newValue.isBlank()) {
return true;
}
String searchKeyword = newValue.toLowerCase();
// 根据 ID 进行过滤 (这里只过滤ID,您可以扩展到其他字段)
return String.valueOf(employee.getId()).toLowerCase().contains(searchKeyword);
});
});
// 5. 将 FilteredList 包装成 SortedList
SortedList<Employee> sortedList = new SortedList<>(filteredList);
// 6. 将 SortedList 的比较器属性绑定到 TableView 的比较器属性
// 这样 TableView 的排序操作会影响 SortedList
sortedList.comparatorProperty().bind(mTableView.comparatorProperty());
// 7. 将 SortedList 设置为 TableView 的数据源
mTableView.setItems(sortedList);
}
/**
* 模拟加载数据到 ObservableList
* 实际应用中会从数据库或其他数据源获取
*/
private void loadRecords() {
mList.add(new Employee(101, "Alice", "50000"));
mList.add(new Employee(102, "Bob", "60000"));
mList.add(new Employee(103, "Charlie", "75000"));
mList.add(new Employee(201, "David", "55000"));
mList.add(new Employee(202, "Eve", "62000"));
mList.add(new Employee(301, "Frank", "80000"));
}
/**
* 处理搜索按钮点击事件
* 获取当前 TableView 中过滤后的数据,并传递给另一个 FXML 视图
*/
@FXML
public void handleSearch(ActionEvent event) {
// 获取 TableView 当前显示的所有项 (这些项已经是经过过滤和排序的)
ObservableList<Employee> currentDisplayedItems = mTableView.getItems();
if (!currentDisplayedItems.isEmpty()) {
// 获取第一个匹配的员工对象
Employee selectedEmployee = currentDisplayedItems.get(0);
System.out.println("Selected Employee (first filtered): " + selectedEmployee.getName() + " (ID: " + selectedEmployee.getId() + ")");
// 示例:加载另一个 FXML 视图并传递数据
try {
// 假设您有一个名为 "DetailView.fxml" 的新视图
FXMLLoader loader = new FXMLLoader(getClass().getResource("/yourpackage/DetailView.fxml"));
Parent root = loader.load();
// 获取新视图的控制器
DetailController detailController = loader.getController();
// 调用新控制器的方法来传递数据
detailController.setEmployeeDetails(selectedEmployee);
// 创建并显示新场景
Stage stage = new Stage();
stage.setTitle("Employee Details");
stage.setScene(new Scene(root));
stage.show();
// 可选:关闭当前窗口
// ((Stage) searchBtn.getScene().getWindow()).close();
} catch (IOException e) {
e.printStackTrace();
// 处理加载 FXML 失败的错误
}
} else {
System.out.println("No employee found matching the filter criteria.");
// 可以在此处显示一个警告框通知用户
}
}
}为了演示数据传递,我们需要一个接收数据的目标 FXML 视图和其对应的控制器。
<!-- DetailView.fxml -->
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="300.0" spacing="10.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="yourpackage.DetailController">
<children>
<Label text="Employee Details">
<font>
<Font size="20.0" />
</font>
</Label>
<Label fx:id="idLabel" text="ID: " />
<Label fx:id="nameLabel" text="Name: " />
<Label fx:id="salaryLabel" text="Salary: " />
</children>
</VBox>// DetailController.java
package yourpackage;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class DetailController {
@FXML
private Label idLabel;
@FXML
private Label nameLabel;
@FXML
private Label salaryLabel;
/**
* 设置员工详细信息到 UI 控件
* @param employee 接收到的员工对象
*/
public void setEmployeeDetails(Employee employee) {
if (employee != null) {
idLabel.setText("ID: " + employee.getId());
nameLabel.setText("Name: " + employee.getName());
salaryLabel.setText("Salary: " + employee.getSalary());
}
}
}通过本教程,您应该已经掌握了在 JavaFX 中实现 TableView 动态过滤的核心技术,包括使用 FilteredList 和 SortedList,以及如何监听 TextField 的输入变化。更重要的是,您学会了如何在按钮点击事件中准确获取 TableView 当前显示的数据,并将其作为参数传递给另一个 FXML 视图的控制器,从而实现复杂的界面交互和数据流转。这些技术是构建功能丰富的 JavaFX 应用的基础。
以上就是JavaFX TableView 动态过滤与选中项获取及跨视图数据传递教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号