有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java绑定属性<Predicate<MyObject>>到ListView(使用SelectionMode.MULTIPLE)

我试图在ListViewObjectProperty之间绑定,其中可以选择多个项目。选择项目时,我希望相应地筛选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列表现在包括当前选择的所有值。 如何将sourceFilterselected列表的所有值绑定

我在考虑迭代列表中的每个值并以这种方式绑定:

  sourceFilter.bind(Bindings.createObjectBinding(() ->

            log -> log.getSource().toLowerCase().contains(selected.getItems().get(i).toLowerCase()),
                sourceList.selectionModelProperty()

    ));

但它似乎不是很优雅,我也不确定我是否以正确的方式使用了selectionModelProperty


共 (1) 个答案

  1. # 1 楼答案

    只有当selectionModel被替换时,selectionModelProperty才会触发更改,这通常不会发生。依赖项应该是sourceList.getSelectionModel().getSelectedItems()

    此外,根据我的理解,您应该查询Logsource是否在所选项目中,而不是source字符串是否在所选项目列表的某个位置包含字符串的某个部分

    还需要注意的是,应该避免仅使用ListView来存储数据,对于大型列表,对Set而不是List进行contains检查要高效得多

    您可以使用如下代码:

    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);