簡體   English   中英

TornadoFX/JavaFX - 根據另一個可觀察屬性過濾可觀察列表

[英]TornadoFX/JavaFX - filter an observable list based on another observable property

我在使用 TorandoFX 找出相對簡單的過濾配置時遇到了一些困難。 我想基於SimpleStringProperty創建一個FilteredList (由ObservableList支持)。 過濾操作應該“綁定”到字符串屬性,這樣對屬性的任何更新都會自動重新執行過濾操作。

例如,假設我想根據字符串屬性的長度過濾列表,以便FilteredList中的所有元素的長度 >= 字符串屬性 以下不起作用。

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 )不會改變。

我如何使此代碼工作?

我不知道 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<Predicate<String>>和要觀察的可觀察值列表(如果有任何無效,則重新計算):

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

}

我想到了。 感謝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在於filterWhen參見文檔)方法。 出於我不明白的原因,它僅適用於SortedFilteredList ,而不是普通的FilteredList filterWhen允許您明確聲明要觀察哪些屬性以進行更改,並且過濾器每次都重新運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM