我有一个TableView,其中包含Person
项的可观察列表。每行显示一个Person
对象,并且还会显示其name
属性。
我想将此observable传递到已过滤的列表中,在名称属性上设置谓词。
我想要达到的目标是:
如果我双击TableView中包含Person
项的任何一行,我将能够提取所选names
对象的Person
属性,并设置谓词筛选列表为选定名称。
因此,筛选后的列表将只包含具有所选名称的Person
个项目。
以下代码几乎可以实现我想要的一切。但是,有一个边缘情况,它无法按预期工作。例如,当我用" name = John"双击该人时。已过滤的列表将过滤名称为" John"的所有人。现在,如果我将已过滤列表中某个人的姓名更改为" Tim"。此人仍保留在已过滤的列表中。理想情况下,我希望将其自动删除。 但我无法这样做。
我认为我没有正确使用setPredicate
,因为我觉得我正在编写冗余代码,应该有更有效的方法来执行此操作,并且会自动删除具有不同名称的人员修改
在我的Person
课程中,
private StringProperty Name;
private final BooleanProperty filteredName = new SimpleBooleanProperty() ;
public final boolean getFilteredName(){
return filteredNameProperty().getValue();
}
public final BooleanProperty filteredNameProperty(){
return this.filteredName;
}
public final void setFilteredName(String name){
if(getName().equals(name)){
this.filteredNameProperty().set(true);
} else{
this.filteredNameProperty().set(false);
}
}
在我的控制器中,我有:
private ObservableList<Person> observableListOfPerson = FXCollections.observableArrayList(p->
new Observable[]{
p.nameProperty(),
p.filteredNameProperty()
}
);
private FilteredList<Person> filterListOfPerson= new FilteredList<>(observableListOfPerson, p-> p.filteredNameProperty().get());
public void initializeFilteredTable(){
filteredTab.setText("Filtered History");
filterTable.setItems(filterListOfPerson);
filterListOfPerson.addListener(new ListChangeListener<Person>(){
@Override
public void onChanged(ListChangeListener.Change change) {
filterTable.setItems(filterListOfPerson);
}
});
filterTable.setItems(filterListOfPerson);}
在AnimatedRow
课程中,我有:
public class AnimatedRow<T> extends TableRow<T> {
private TabPane fxTabPaneLower;
/**
* The data as an observable list of Person.
*/
private ObservableList<Person> observableListOfPerson;
private FilteredList<Person> filterListOfPerson;
public AnimatedRow(Function<T, StringExpression> nameExtractor, ObservableList<Person> observableListOfPerson, FilteredList<Person> filterListOfPerson, TabPane fxTabPaneLower) {
setOnMouseClicked(event -> {
if (event.getClickCount() == 2 && (!isEmpty()) ) {
final StringExpression nameBE = nameExtractor.apply(getItem());
for(Person t : observableListOfPerson){
t.setFilteredName(nameBE.get());
}
filterListOfPerson.setPredicate(p-> p.filteredNameProperty().get());
fxTabPaneLower.getSelectionModel().select(1);
((TableView<Person>)fxTabPaneLower.getTabs().get(1).getContent()).setItems(filterListOfPerson);
}
});
}
}
答案 0 :(得分:1)
(这基本上是JavaFX FilteredList, filtering based on property of items in the list的副本。)
您似乎正在尝试在Person
课程中实施过滤。 FilteredList
的重点在于它为您实现了过滤器。
所以我认为你完全摆脱filteredName
财产然后再做
public AnimatedRow(Function<T, StringExpression> nameExtractor, ObservableList<Person> observableListOfPerson, FilteredList<Person> filterListOfPerson, TabPane fxTabPaneLower) {
setOnMouseClicked(event -> {
if (event.getClickCount() == 2 && (!isEmpty()) ) {
final StringExpression nameBE = nameExtractor.apply(getItem());
filterListOfPerson.setPredicate(p-> p.getName().equals(nameBE.get()));
fxTabPaneLower.getSelectionModel().select(1);
((TableView<Person>)fxTabPaneLower.getTabs().get(1).getContent()).setItems(filterListOfPerson);
}
});
}
只要您将name属性作为基础列表的提取器的一部分返回,当名称更改时,将重新评估过滤器。