Search code examples
javakotlinjavafxtornadofx

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


I'm having some difficulty figuring out a relatively simple filtering configuration with TorandoFX. I would like to create a FilteredList (backed by an ObservableList) based on a SimpleStringProperty. The filter operation should be "bound" to the string property, so that any updates to the property automatically re-execute the filter operation.

For example, say I want to filter the list based on the length of the string property so that all elements in the FilteredList have length >= the string property. The following does not work.

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

I hooked this interface into a GUI, but as I type into the textfield (bound to the SimpleStringProperty the combobox (bound to the filteredList) does not change.

How do I make this code work?


Solution

  • I figured it out. Thanks to James_D for pointing me in the right direction with Predicates. And thanks to others who have provided examples in JavaFX (which guided me to the TornadoFX/Kotlin answer).

    Here's the answer in 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}
    }
    

    The magic here is the filterWhen (see docs) method. For reasons I don't understand, it's only available on a SortedFilteredList, not a plain FilteredList. filterWhen lets you explicitly declare what properties are to be observed for change and the filter re-run each time.