Как реорганизовать представление, чтобы разрешить фильтрацию элементов, привязанных к наблюдаемомуArrayList, внутри приложения tornadofx

Я начал с примера hello-world нашел https://github.com:JetBrains/kotlin-examples.git и изменил его, чтобы использовать TornadoFX.

Это приложение, которое отображает список элементов. Вы можете добавить в список, и RequestView автоматически отобразит все элементы.

Я работаю так, чтобы сохраненные элементы привязывались к observableArrayList но теперь я хочу реализовать фильтр, используя TextView внизу. Но я пытаюсь понять, означает ли это, что я должен создать новый список, который управляется внутренне в RequestView , и фильтровать его или как это сделать.

 package demo import javafx.collections.FXCollections import javafx.geometry.Pos import javafx.scene.control.TextField import javafx.scene.layout.VBox import javafx.scene.text.FontWeight import tornadofx.* class helloWorldApp : App(HelloWorld::class) { } class HelloWorld : View() { override val root = VBox() var requestView: RequestView by singleAssign() var filterField: TextField by singleAssign() init { with(root) { requestView = RequestView() this += requestView filterField = TextField() this += filterField } requestView.items.add("Hi there") requestView.items.add("Another one") } } class RequestView() : View() { var items = FXCollections.observableArrayList<String>() override val root = listview(items) { cellFormat { graphic = cache { form { fieldset { label(it) { alignment = Pos.CENTER_LEFT style { fontSize = 15.px fontWeight = FontWeight.BOLD } } } } } } } } 

Вот файл build.gradle, на всякий случай это полезно.

 buildscript { ext.kotlin_version = '1.1.2' repositories { mavenCentral() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } apply plugin: 'kotlin' apply plugin: 'application' mainClassName = 'demo.helloWorldApp' defaultTasks 'run' repositories { mavenCentral() } tasks.compileKotlin.kotlinOptions.jvmTarget = "1.8" dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" testCompile 'junit:junit:4.11' testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" compile 'no.tornado:tornadofx:1.7.10' } task wrapper(type: Wrapper) { gradleVersion = "2.7" } 

Вы должны использовать SortedFilteredList который обертывает ObservableList и принимает предикат, который используется для различения записей.

Существует несчастливая связь между двумя вашими представлениями, поэтому вам стоит подумать об обстреле события, но вот рабочее решение с минимальными изменениями к вашему примеру. Я переместил данные в модель и очистил код ui, а также избавился от операторов singleAssign и применил некоторые лучшие практики для строителей 🙂

Как вы можете видеть, у SortedFilteredList есть функция filterWhen которая будет вызываться всякий раз, когда изменяется текстовое поле textProperty() .

 class HelloWorldApp : App(HelloWorld::class) class HelloWorld : View() { val requestView: RequestView by inject() override val root = vbox { add(requestView) textfield { promptText = "Filter" requestView.data.filterWhen(textProperty()) { query, item -> item.contains(query, ignoreCase = true) } } } } class ItemsModel : ViewModel() { val items = FXCollections.observableArrayList<String>() fun addItem(item: String) = items.add(item) init { addItem("Hi there") addItem("Another one") } } class RequestView() : View() { val model: ItemsModel by inject() val data = SortedFilteredList(model.items) override val root = listview(data) { cellFormat { graphic = cache { form { fieldset { label(it) { alignment = Pos.CENTER_LEFT style { fontSize = 15.px fontWeight = FontWeight.BOLD } } } } } } } }