我使用带有监听器的 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);
以下是表格中的基本示例数据
与列表中第一个对象匹配的搜索图像,但标签仍然显示
与列表中第二个对象匹配的搜索图像,但标签仍然显示
只要表格中的最后一个对象包含在搜索中,标签图像就可以工作
最佳答案
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
.另外(这只是样式,而不是功能),为了帮助使代码更易于阅读,请在监听器中为新文本使用描述性名称(例如 filterText
或 newSearchText
而不是 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/