【发布时间】:2015-09-22 17:57:02
【问题描述】:
我有一个包含Person 项目的可观察列表的 TableView。每行显示一个Person 对象,同时还显示其name 属性。
我想将此 observable 传递到过滤列表中并在 name 属性上设置谓词。
我想要实现的是:
如果我双击 TableView 中包含Person 项目的任何一行,我将能够提取所选Person 对象的names 属性并将过滤列表的谓词设置为选中名称。
因此过滤后的列表将仅包含 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);
}
});
}
}
【问题讨论】:
-
难道你不需要在名称更新的提交上过滤列表吗?
-
@purringpigeon 不,您只需要确保基础列表在属性更改时触发更新。
-
在发布此问题之前,我查看了该问题,并且我在您为该问题发布的答案中做了所有事情。我添加了
new ObservableList[] {p -> p.NameProperty()....} -
是的,我最初错过了。我真的不明白
filteredName的目的。除了过滤之外,您还使用它吗? -
基本上,
filteredListOfPerson是我的第二个表格视图。因此,如果我在包含所有 Person 项目的第一个表视图中单击 Person 的名称,filteredListOfPerson将按所选名称过滤第一个表中的所有 Person 项目,并在第二个表视图中显示结果。这一切都很好,直到我开始编辑第二个表中的 Person 项目,然后我意识到如果我在filteredListOfPerson中更改了 Person 的名称,它仍然会保留在第二个表中。