【问题标题】:TornadoFX/JavaFX - filter an observable list based on another observable propertyTornadoFX/JavaFX - 根据另一个可观察属性过滤可观察列表
【发布时间】:2020-03-04 14:00:30
【问题描述】:

我在用 TorandoFX 找出一个相对简单的过滤配置时遇到了一些困难。我想基于SimpleStringProperty 创建一个FilteredList(由ObservableList 支持)。过滤操作应该“绑定”到字符串属性,以便对属性的任何更新都会自动重新执行过滤操作。

例如,假设我想根据字符串属性的 length 过滤列表,以便FilteredList 中的所有元素都具有 length >= string 属性。以下不起作用。

val prop = SimpleStringProperty()
val baseList = listOf("a", "aa", "aaa", "b", "bb", "bbb")
val filteredList = FilteredList(baseList){ t -> prop.length().lessThanOrEqualTo(t.length).get()}

我将此界面连接到 GUI 中,但是当我在文本字段(绑定到 SimpleStringProperty)中键入时,组合框(绑定到 filteredList)并没有改变。

如何使这段代码工作?

【问题讨论】:

    标签: java kotlin javafx tornadofx


    【解决方案1】:

    我不知道 Kotlin/TornadoFX,但这是您(或其他人)可能能够翻译的 JavaFX 解决方案。

    基本思想是创建FilteredList 并将其predicateProperty 绑定到依赖于适当StringPropertyPredicate。有多种库方法可用于创建此类绑定。例如。你可以这样做:

    filteredList = new FilteredList<>(baseList);
    filteredList.predicateProperty().bind(
        new ObjectBinding<>() {
            {
                super.bind(prop);
            }
            @Override
            public Predicate<String> computeValue() {
                return t -> t.length() > prop.get().length() ;
            }
        }
    );
    

    您还可以使用Bindings.createBinding() 方法,该方法采用Callable&lt;Predicate&lt;String&gt;&gt; 和要观察的可观察对象列表(如果有任何无效,则重新计算):

    filteredList.predicateProperty().bind(Bindings.createObjectBinding(
        // Callable<Predicate<String>> expressed as a lambda: () -> Predicate<String>
        () ->
            // Predicate<String> expressed as a lambda: String -> boolean
            t -> t.length() > prop.get().length(),
        prop
    ));
    

    如果没有评论,那就简明扼要(但令人难以置信)

    filteredList.predicateProperty().bind(Bindings.createObjectBinding(
        () -> t -> t.length() > prop.get().length(),
        prop
    ));
    

    这是一个完整的例子:

    import static javafx.beans.binding.Bindings.createObjectBinding;
    
    import javafx.application.Application;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.collections.transformation.FilteredList;
    import javafx.scene.Scene;
    import javafx.scene.control.ListView;
    import javafx.scene.control.TextField;
    import javafx.scene.layout.BorderPane;
    import javafx.stage.Stage;
    
    public class FilteredListExample extends Application {
    
        @Override
        public void start(Stage primaryStage) throws Exception {
    
            ObservableList<String> baseList = FXCollections.observableArrayList("a", "aa", "aaa", "b", "bb", "bbb");
            FilteredList<String> filteredList = new FilteredList<>(baseList);
    
            ListView<String> listView = new ListView<>(filteredList);
    
            TextField input = new TextField();
    
            filteredList.predicateProperty().bind(createObjectBinding(
                    () -> t -> t.length() >= input.getText().length(),
                    input.textProperty()));
    
    
            BorderPane root = new BorderPane(listView, input, null, null, null) ;
            Scene scene = new Scene(root);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) { Application.launch(args); }
    
    }
    

    【讨论】:

      【解决方案2】:

      我想通了。感谢 James_DPredicates 为我指明了正确的方向。并感谢其他在 JavaFX 中提供示例的人(引导我找到 TornadoFX/Kotlin 的答案)。

      这是 Kotlin 中的答案:

      val prop = SimpleStringProperty()
      val baseList = listOf("a", "aa", "aaa", "b", "bb", "bbb")
      val filteredList = SortedFilteredList(baseList).apply {
              filterWhen(prop) {prop, item -> (prop?.length ?: 0) <= item.length}
      }
      

      这里的神奇之处在于filterWhen (see docs) 方法。由于我不明白的原因,它仅在SortedFilteredList 上可用,而不是在普通的FilteredList 上可用。 filterWhen 允许您明确声明要观察哪些属性以进行更改,并且每次都会重新运行过滤器。

      【讨论】:

        猜你喜欢
        • 2018-06-20
        • 2019-11-20
        • 2020-08-05
        • 1970-01-01
        • 1970-01-01
        • 2023-04-08
        • 2016-10-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多