Javafx:过滤列表

时间:2015-09-22 17:57:02

标签: java javafx

我有一个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);              
          }
        });
    }
}

1 个答案:

答案 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属性作为基础列表的提取器的一部分返回,当名称更改时,将重新评估过滤器。