讲师中心 微信公众号
AI工具推荐 视频效率加速

JavaFX TableView筛选与搜索结果动态获取教程

千宇酱_1298

千宇酱_1298

发布时间:2025-11-07 15:31:01

|

611人浏览过

|

来源于php中文网

原创

JavaFX TableView筛选与搜索结果动态获取教程

本教程详细讲解如何在javafx应用中实现tableview的数据筛选功能,并通过文本输入框和按钮交互,动态获取筛选后的数据。文章将涵盖filteredlist和sortedlist的使用、文本监听器实现实时筛选,以及在按钮点击事件中准确获取当前tableview中显示的数据项,并探讨如何将这些数据传递给其他fxml视图进行进一步处理。

在JavaFX应用程序中,TableView 是一个功能强大的组件,常用于展示大量结构化数据。当数据量较大时,提供搜索和筛选功能可以极大地提升用户体验。本教程将指导您如何结合 TextField 和 Button,实现对 TableView 数据的动态筛选,并在用户点击搜索按钮后,获取并处理筛选后的结果。

核心概念:JavaFX TableView的筛选机制

JavaFX提供了一套灵活的机制来管理和筛选 TableView 的数据。主要涉及到以下几个关键类:

  1. ObservableList: 存储 TableView 的原始数据。任何对该列表的修改都会自动反映在 TableView 上。
  2. FilteredList: 包装一个 ObservableList,并根据一个 Predicate 对象来过滤数据。当 Predicate 发生变化时,FilteredList 会自动更新其内容。
  3. SortedList: 包装一个 FilteredList (或任何 ObservableList),并根据 TableView 的排序规则来排序数据。它允许用户通过点击列头进行排序。

通过将 FilteredList 绑定到 TextField 的文本变化监听器上,我们可以实现实时搜索功能。

准备工作:FXML布局与控制器骨架

首先,我们需要一个包含 TableView、TextField 和 Button 的FXML布局文件。

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

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<GridPane xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.TableController">
    <columnConstraints>
        <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
    </columnConstraints>
    <rowConstraints>
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    </rowConstraints>
    <HBox alignment="CENTER_LEFT" prefHeight="100.0" prefWidth="200.0" spacing="10.0">
        <TextField fx:id="mTextField" prefHeight="28.0" prefWidth="366.0" promptText="输入ID搜索" />
        <Button fx:id="searchBtn" mnemonicParsing="false" onAction="#handleSearch" prefHeight="26.0" prefWidth="166.0" text="搜索" />
    </HBox>
    <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>
    </TableView>
</GridPane>

接下来,是对应的控制器骨架和数据模型。

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<Employee> mTableView;
    @FXML
    private TableColumn<Employee, Integer> idColumn;
    @FXML
    private TableColumn<Employee, String> nameColumn;
    @FXML
    private TableColumn<Employee, Double> salColumn; // 假设Salary是Double类型
    @FXML
    private TextField mTextField;
    @FXML
    private Button searchBtn;

    private ObservableList<Employee> mList = FXCollections.observableArrayList();
    private FilteredList<Employee> filteredList;
    private SortedList<Employee> 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<Employee>
     */
    private Predicate<Employee> 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数据模型:

JavaStoryDevelop
JavaStoryDevelop

你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在

下载
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<Employee> 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);
        }
    }

数据传递与多FXML场景

在实际应用中,您可能需要将筛选出的数据(例如 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 示例:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox alignment="CENTER" spacing="10.0" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.example.DetailController">
    <Label fx:id="idLabel" text="ID:" />
    <Label fx:id="nameLabel" text="姓名:" />
    <Label fx:id="salaryLabel" text="薪水:" />
</VBox>

注意事项与最佳实践

  1. 处理空结果集: 在 handleSearch 方法中,务必检查 currentDisplayedEmployees 是否为空。如果为空,应向用户提供适当的反馈(例如,弹出一个提示框)。
  2. 处理多结果集: 如果筛选后有多个结果,您需要决定如何处理。
    • 选择第一个: 如示例所示,直接获取 get(0)。
    • 全部处理: 遍历整个 currentDisplayedEmployees 列表。
    • 用户选择: 如果希望用户从多个结果中手动选择,可以考虑在 TableView 中添加一个选择列,或者弹出一个新的 Dialog 让用户进行选择。
  3. 性能优化: 对于非常大的数据集(数万甚至数十万条记录),实时筛选可能会有性能问题。可以考虑:
    • 延迟搜索: 使用 Platform.runLater 或 Timeline 在用户停止输入一段时间后才执行筛选。
    • 后端搜索: 将搜索逻辑移到后端服务,只加载匹配的数据。
  4. 错误处理: 在加载新的FXML文件时,FXMLLoader.load() 可能会抛出 IOException。务必捕获并处理这些异常,向用户提供友好的错误信息。
  5. Predicate逻辑: createSearchPredicate 方法中的逻辑可以根据您的需求进行扩展。例如,可以支持多个字段的组合搜索,或者更复杂的匹配规则(如正则表达式)。

总结

通过本教程,您应该已经掌握了如何在JavaFX中实现 TableView 的动态筛选功能。核心在于利用 FilteredList 和 SortedList 来管理数据视图,并通过 TextField 的文本监听器实时更新筛选条件。在按钮点击事件中,mTableView.getItems() 方法是获取当前筛选后数据集合的关键。结合 FXMLLoader,您可以轻松地将这些数据传递到其他视图,构建更加复杂和交互性强的JavaFX应用程序。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

相关专题

更多
js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

4396

2023.06.20

正则表达式不包含
正则表达式不包含

正则表达式,又称规则表达式,,是一种文本模式,包括普通字符和特殊字符,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式的文本。php中文网给大家带来了有关正则表达式的相关教程以及文章,希望对大家能有所帮助。

2921

2023.07.05

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

8042

2023.07.05

java正则表达式匹配字符串
java正则表达式匹配字符串

在Java中,我们可以使用正则表达式来匹配字符串。本专题为大家带来java正则表达式匹配字符串的相关内容,帮助大家解决问题。

812

2023.08.11

正则表达式空格
正则表达式空格

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。本专题为大家提供正则表达式相关的文章、下载、课程内容,供大家免费下载体验。

520

2023.08.31

Python爬虫获取数据的方法
Python爬虫获取数据的方法

Python爬虫可以通过请求库发送HTTP请求、解析库解析HTML、正则表达式提取数据,或使用数据抓取框架来获取数据。更多关于Python爬虫相关知识。详情阅读本专题下面的文章。php中文网欢迎大家前来学习。

673

2023.11.13

正则表达式空格如何表示
正则表达式空格如何表示

正则表达式空格可以用“s”来表示,它是一个特殊的元字符,用于匹配任意空白字符,包括空格、制表符、换行符等。想了解更多正则表达式空格怎么表示的内容,可以访问下面的文章。

386

2023.11.17

正则表达式中如何匹配数字
正则表达式中如何匹配数字

正则表达式中可以通过匹配单个数字、匹配多个数字、匹配固定长度的数字、匹配整数和小数、匹配负数和匹配科学计数法表示的数字的方法匹配数字。更多关于正则表达式的相关知识详情请看本专题下面的文章。php中文网欢迎大家前来学习。

719

2023.12.06

Playwright 测试失败怎么办
Playwright 测试失败怎么办

Playwright测试失败专题汇集超时、定位器匹配、浏览器提前关闭、依赖与插件配置、文件上传、SSL及Docker启动等故障文章,并介绍通过截图、报告和Trace定位错误。

0

2026.10.21

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn