JavaFX FilteredList,基于列表中项目的属性进行过滤 [英] JavaFX FilteredList, filtering based on property of items in the list

查看:178
本文介绍了JavaFX FilteredList,基于列表中项目的属性进行过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个案例需要根据项目的某些属性过滤 ObservableList< Item> (即条件是内部条件而非外部条件)。我发现javafx有 FilteredList 所以我试了一下。我可以设置谓词和过滤工作,直到确定过滤的属性值发生变化。设置谓词现在完成如下:

I have a case where I need to filter a ObservableList<Item> based on some properties of the items (i.e. the condition is internal and not external). I found out that javafx has FilteredList so I tried it. I could set the predicate and filtering works, until the property value that determines the filtering changes. Setting the predicate is done now like following:

list.setPredicate(t -> !t.filteredProperty().get())

由于谓词返回boolean而不是BooleanProperty,因此对该属性的更改不会反映在list。

Since the predicate returns boolean and not BooleanProperty, the changes to that property are not reflected on the list.

这有什么简单的解决方案吗?我可以尝试做一些解决方法,例如创建一个单独的列表并同步,或者每次属性在一个项目中更改时重置谓词,希望重新触发过滤,但我首先想问一下,如果有人知道一个漂亮的解决方案,因为这些变通办法当然不是。

Is there any easy solution to this? I could try to do some workarounds, e.g. create a separate list and sync that, or reset the predicate every time the property changes in one item hopefully retriggering the filtering, but I first wanted to ask in case someone knows a pretty solution as those workarounds certainly are not.

推荐答案

使用提取器。这将使基础列表在任何元素的 filteredProperty()更改时触发更新事件。 FilteredList 将观察这些事件,因此会相应更新:

Create the underlying list with an extractor. This will enable the underlying list to fire update events when the filteredProperty() of any elements change. The FilteredList will observe these events and so will update accordingly:

ObservableList<Item> baseList = FXCollections.observableArrayList(item -> 
    new Observable[] {item.filteredProperty()});
FilteredList<Item> list = new FilteredList<>(baseList, t -> ! t.filteredProperty().get());

快速演示:

import java.util.stream.IntStream;

import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener.Change;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;


public class DynamicFilteredListTest {

    public static void main(String[] args) {

        ObservableList<Item> baseList = FXCollections.observableArrayList(item -> 
                new Observable[] {item.filteredProperty()});

        FilteredList<Item> list = new FilteredList<>(baseList, t -> ! t.isFiltered());

        list.addListener((Change<? extends Item> c) -> {
            while (c.next()) {
                if (c.wasAdded()) {
                    System.out.println(c.getAddedSubList()+ " added to filtered list");
                }
                if (c.wasRemoved()) {
                    System.out.println(c.getRemoved()+ " removed from filtered list");
                }
            }
        });

        System.out.println("Adding ten items to base list:\n");

        IntStream.rangeClosed(1, 10).mapToObj(i -> new Item("Item "+i)).forEach(baseList::add);

        System.out.println("\nFiltered list now:\n"+list);

        System.out.println("\nSetting filtered flag for alternate items in base list:\n");

        IntStream.range(0, 5).map(i -> 2*i).mapToObj(baseList::get).forEach(i -> i.setFiltered(true));

        System.out.println("\nFiltered list now:\n"+list);
    }


    public static class Item {
        private final StringProperty name = new SimpleStringProperty() ;
        private final BooleanProperty filtered = new SimpleBooleanProperty() ;

        public Item(String name) {
            setName(name);
        }

        public final StringProperty nameProperty() {
            return this.name;
        }

        public final String getName() {
            return this.nameProperty().get();
        }

        public final void setName(final String name) {
            this.nameProperty().set(name);
        }

        public final BooleanProperty filteredProperty() {
            return this.filtered;
        }

        public final boolean isFiltered() {
            return this.filteredProperty().get();
        }

        public final void setFiltered(final boolean filtered) {
            this.filteredProperty().set(filtered);
        }

        @Override
        public String toString() {
            return getName();
        }
    }
}

这篇关于JavaFX FilteredList,基于列表中项目的属性进行过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆