0

0

JavaFX TableView 动态过滤与选中项获取及跨视图数据传递教程

霞舞

霞舞

发布时间:2025-11-07 13:46:12

|

432人浏览过

|

来源于php中文网

原创

JavaFX TableView 动态过滤与选中项获取及跨视图数据传递教程

本教程详细阐述了如何在 javafx 中实现 tableview 的动态数据过滤功能,通过 textfield 实时更新显示内容。重点讲解了如何在用户点击按钮时,从已过滤的 tableview 中准确获取当前显示的数据(特别是第一个匹配项),并演示了如何将这些获取到的数据安全地传递给另一个 fxml 视图及其控制器,以实现复杂的应用交互逻辑。

JavaFX TableView 高级用法:实现动态过滤与选中项获取

在 JavaFX 应用开发中,TableView 是一个常用的组件,用于展示结构化数据。当数据量较大时,用户往往需要通过搜索或过滤功能来快速定位所需信息。本教程将指导您如何实现一个带有动态过滤功能的 TableView,并在用户点击按钮时,获取当前过滤结果中的数据,并将其传递给另一个 FXML 视图。

1. 核心组件概览

为了实现动态过滤和数据获取,我们将使用以下 JavaFX 组件和集合类:

  • TableView: 显示数据的表格。
  • TableColumn: TableView 中的列定义。
  • TextField: 用户输入过滤关键词的文本框。
  • Button: 触发数据获取和视图切换的按钮。
  • ObservableList: 存储原始数据,支持数据变更通知。
  • FilteredList: 基于 ObservableList 创建,通过 Predicate 实现数据过滤。
  • SortedList: 基于 FilteredList 创建,支持数据排序,并最终绑定到 TableView。

2. 构建数据模型

首先,我们需要一个简单的数据模型来表示表格中的每一行。以 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);
    }
}

3. FXML 布局配置

在 FXML 文件中,我们需要定义 TableView、TextField 和 Button。确保为它们设置 fx:id 和 onAction 属性,以便在控制器中引用和处理事件。

立即学习Java免费学习笔记(深入)”;

闪念贝壳
闪念贝壳

闪念贝壳是一款AI 驱动的智能语音笔记,随时随地用语音记录你的每一个想法。

下载
<!-- 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>

4. 控制器逻辑实现

控制器是实现所有业务逻辑的地方。我们将在这里初始化 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.");
            // 可以在此处显示一个警告框通知用户
        }
    }
}

5. 创建目标 FXML 视图及控制器

为了演示数据传递,我们需要一个接收数据的目标 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());
        }
    }
}

6. 注意事项与最佳实践

  • 获取过滤后的数据: 关键在于 mTableView.getItems() 方法。它返回的是 TableView 当前实际显示的数据(已经过 FilteredList 和 SortedList 处理)。直接访问 mList 或 filteredList 将无法反映 TableView 当前的显示状态。
  • 处理空结果集: 在 handleSearch 方法中,务必检查 currentDisplayedItems.isEmpty()。如果 TableView 中没有匹配项,尝试 get(0) 会导致 IndexOutOfBoundsException。
  • 处理多结果集: 当前示例只获取了第一个匹配项 (get(0))。如果需要处理所有匹配项,您可以遍历 currentDisplayedItems 列表。如果业务逻辑要求用户从多个匹配项中选择一个,您可能需要提供一个选择界面,或者修改 TableView 的选择模型。
  • 性能优化: 对于非常大的数据集,过滤操作可能会影响性能。考虑使用更高效的数据结构或在后台线程中执行复杂的过滤逻辑。
  • 错误处理: 在加载 FXML 文件时,务必捕获 IOException,并提供友好的错误提示。
  • 代码模块化: 将数据加载、过滤逻辑等拆分成独立的私有方法,提高代码的可读性和可维护性。
  • PropertyValueFactory 参数: PropertyValueFactory 构造函数中的字符串参数必须与数据模型 (Employee 类) 中属性的 getter 方法名匹配(例如,"id" 对应 getId() 和 idProperty())。

总结

通过本教程,您应该已经掌握了在 JavaFX 中实现 TableView 动态过滤的核心技术,包括使用 FilteredList 和 SortedList,以及如何监听 TextField 的输入变化。更重要的是,您学会了如何在按钮点击事件中准确获取 TableView 当前显示的数据,并将其作为参数传递给另一个 FXML 视图的控制器,从而实现复杂的界面交互和数据流转。这些技术是构建功能丰富的 JavaFX 应用的基础。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

1228

2024.03.22

php中定义字符串的方式
php中定义字符串的方式

php中定义字符串的方式:单引号;双引号;heredoc语法等等。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

1205

2024.04.29

go语言字符串相关教程
go语言字符串相关教程

本专题整合了go语言字符串相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.07.29

c++字符串相关教程
c++字符串相关教程

本专题整合了c++字符串相关教程,阅读专题下面的文章了解更多详细内容。

131

2025.08.07

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.4万人学习

C# 教程
C# 教程

共94课时 | 11.3万人学习

Java 教程
Java 教程

共578课时 | 82.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号