java - JavaFX 中过滤列表搜索的标签可见性

标签 java javafx label listener predicate

我使用带有监听器的 TextField 来过滤 TableView。我有 if 语句,如果 newText 与 ID 或名称的一部分匹配,则设置谓词。

搜索功能如我所愿。

但是,我的项目指南要求我在搜索与 TableView 中的任何对象不匹配时创建某种形式的输出。

我创建了一个标签并将可见性设置为 false 以启动。我在谓词逻辑中的每个 if 语句之后放置了将标签设置为可见的代码,以便它仅在所有语句均无效时显示。然后,我在谓词逻辑的开头放置了一行将其设置回 false,以便在每个监听器更改时它都会重置。

我遇到一个问题,如果我的搜索返回列表中的最后一项,那么标签不会出现,但如果搜索不返回列表中的最后一项,那么标签甚至会变得可见尽管搜索显示排序列表中的项目。

以下是我的代码,我附上了“错误”的屏幕截图。

FilteredList<Part> filteredParts = new FilteredList<>(Inventory.getAllParts(), p -> true);       

partFilter.textProperty().addListener((ob, ol, newValue) -> {
    filteredParts.setPredicate(text -> {

        //each time listener is updated sets label visibility to false
        partSearchMismatch.setVisible(false);

        //If searchbar is empty or null it displays all parts
        if (newValue == null || newValue.isEmpty()){
            return true;
        }
        //if text matches partID
        String lowerCaseFilter = newValue.toLowerCase();
        if(String.valueOf(text.getId()).contains(lowerCaseFilter)){

            return true;
        }
        //if text matches part name
        if(text.getName().toLowerCase().contains(lowerCaseFilter)){
            return true;
        }


        partSearchMismatch.setVisible(true); //if no matches, displays label 

        return false; //no match

    });

});
//Wraps filtered list in sorted list
SortedList<Part> sortedParts = new SortedList<>(filteredParts);

//Binds sorted list comparator to the parts table comparator
sortedParts.comparatorProperty().bind(partsTable.comparatorProperty());

partsTable.setItems(sortedParts);

以下是表格中的基本示例数据

image1

与列表中第一个对象匹配的搜索图像,但标签仍然显示

image2

与列表中第二个对象匹配的搜索图像,但标签仍然显示

image3

只要表格中的最后一个对象包含在搜索中,标签图像就可以工作

image4

最佳答案

my project guidelines require me to also create some form of output upon a search not matching any objects in the TableView.

默认情况下会发生这种情况,当过滤后的表没有任何与过滤器匹配的内容时,该表将显示 placeholder 。占位符节点是可配置的,因此您可以将其设置为显示任何您想要的内容。

您不需要额外的标签和逻辑来表明表格中不会显示任何内容,除非您有额外的要求。

Okay, so it's the placeholder text that I see in the table that says "no content in table"? I should just be able to set that to something that mentions the search didn't return anything. Thank you. I am still curious what I am doing wrong with the label though

谓词是一个 boolean 函数,执行时应该没有副作用。您在筛选列表上设置谓词,但您不知道或无法控制筛选列表何时选择执行该代码。谓词可以执行多次以过滤列表中的每个单独项目。如果您在谓词中添加副作用(例如设置标签可见性),那么您并不真正知道会发生什么,除非操作是 idempotent (他们不是)。

相反,让谓词评估 lambda 输入对象以查看是否应过滤它,仅返回 true 或 false,而不执行其他操作。

将谓词的输入参数命名为 text 表明您并不真正理解它。输入参数是一个 Part,观察列表的一个元素,它不是文本,因此将其命名为 part 而不是 text.另外(这只是样式,而不是功能),为了帮助使代码更易于阅读,请在监听器中为新文本使用描述性名称(例如 filterTextnewSearchText 而不是 newValue)。

有关使用过滤列表和文本字段搜索表的具体示例,请参阅 Eden 编码教程:

正如 Slaw 在评论中指出的:

If the placeholder is not enough, I would try to use bindings.

Something like:

label.visibleProperty().bind(
    Bindings.isEmpty(filteredParts)
        .and(
             partFilter.textProperty().isNotEmpty()
        )
    )
);

或者,您可以将标签通知设置的逻辑移出谓词,但将其保留在搜索文本字段的更改监听器中(这本质上与绑定(bind)执行类似的工作)。

关于java - JavaFX 中过滤列表搜索的标签可见性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72793598/

相关文章:

java - 当 getter 方法为我做同样的工作时,为什么我需要 setter 方法?

java - 如何在JavaFX TextArea中显示日志?

html - 使用标签、href 和 css 的链接在 IE 中不起作用

javascript - 当<a>包含使用javascript的子元素时如何获取<a>标签的 'aria-label'属性

java - Spring Boot 使用带有通用字段的类来使用 REST API,该字段未转换为正确的类型。我究竟做错了什么?

java - 使用 WAN IP 而不是本地主机的 RESTful Web 应用程序

java - 从单个源文件夹 Gradle 多个 jar

java - Switch 语句关键事件为 1

css - 是否可以使 JavaFX TableColumn 的标题文本溢出到另一列?

c++ - 错误 : Label "foo" used but not defined