为了账号安全,请及时绑定邮箱和手机立即绑定

将 Property<Predicate<MyObject>> 绑定到 ListView

将 Property<Predicate<MyObject>> 绑定到 ListView

温温酱 2021-07-09 14:47:41
我试图在一个ListView可以选择多个项目的地方和一个ObjectProperty. 当一个项目被选中时,我想相应地过滤一TableView列:使用两个较低的过滤器(组件、详细信息),我进行如下绑定:ObjectProperty<Predicate<Log>> detailsSearchFilter = new SimpleObjectProperty<>();TextField detailsSearchField = new TextField();detailsSearchField.setPromptText("e.g. finished initializing");detailsSearchFilter.bind(Bindings.createObjectBinding(() ->                    log -> log.getDetails().toLowerCase().contains(detailsSearchField.getText().toLowerCase()),            detailsSearchField.textProperty()    ));然后稍后添加逻辑运算符方法and()以便能够组合所有过滤器:logFilteredList.predicateProperty().bind(Bindings.createObjectBinding(() ->                    detailsSearchFilter.get().and(componentSearchFilter.get()).and(sourceFilter.get()),            detailsSearchFilter, componentSearchFilter, sourceFilter    ));对于其他两个ListView过滤器,我正在考虑做这样的事情:private final static String[] sources = new String[]{"ECS","IISNode","PrismWebServer"};ListView<String> sourceList = new ListView<>();ObservableList sourceItems = FXCollections.observableArrayList(sources);sourceList.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);sourceList.getItems().addAll(sources);ListView<String> selected = new ListView<>();sourceList.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {        selected.setItems(sourceList.getSelectionModel().getSelectedItems());        System.out.println(Arrays.toString(selected.getItems().toArray()));    });因此该selected列表现在包括当前选择的所有值。如何将sourceFilter与selected列表的所有值绑定?我正在考虑遍历列表中的每个值并以这种方式绑定:  sourceFilter.bind(Bindings.createObjectBinding(() ->            log -> log.getSource().toLowerCase().contains(selected.getItems().get(i).toLowerCase()),                sourceList.selectionModelProperty()    ));但这似乎不是很优雅,我不确定我是否selectionModelProperty以正确的方式使用。
查看完整描述

1 回答

?
郎朗坤

TA贡献1921条经验 获得超9个赞

的selectionModelProperty时候才会触发改变selectionModel被替换这通常不会发生。依赖关系应该是sourceList.getSelectionModel().getSelectedItems().


此外,按照我的理解,您应该查询Log'ssource是否在所选项目中,而不是该source字符串是否在所选项目列表中的某个位置包含字符串的某些部分。


另请注意,ListView应避免仅使用 a来存储数据,对于大型列表,contains对 aSet而不是 a进行检查效率更高List。


你可以使用这样的代码:


ObjectBinding<Predicate<Log>> binding = new ObjectBinding<Predicate<String>>() {

    private final Set<String> strings = new HashSet<>();


    {

        sourceList.getSelectionModel().getSelectedItems().addListener(new ListChangeListener<String>() {


            @Override

            public void onChanged(ListChangeListener.Change<? extends String> c) {

                boolean changed = false;


                // modify set on selection change

                while (c.next()) {

                    if (c.wasRemoved()) {

                        changed = true;

                        c.getRemoved().stream().map(String::toLowerCase).forEach(strings::remove);

                    }

                    if (c.wasAdded()) {

                        changed = true;

                        c.getAddedSubList().stream().map(String::toLowerCase).forEach(strings::add);

                    }

                }


                if (changed) {

                    invalidate();

                }

            }

        });

    }


    @Override

    protected Predicate<Log> computeValue() {

        return log -> strings.contains(log.getSource().toLowerCase());

    }


};

sourceFilter.bind(binding);


查看完整回答
反对 回复 2021-07-14

添加回答

代码语言

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号