如何重构视图以允许过滤在tornadofx应用程序内绑定到observableArrayList的项目

时间:2017-11-15 21:59:10

标签: kotlin observable tornadofx

我开始使用gra 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"
}

1 个答案:

答案 0 :(得分:2)

您应该使用包含ObservableList的SortedFilteredList并接受用于区分条目的谓词。

您的两个视图之间存在令人遗憾的耦合,因此您应该考虑触发事件,但这是一个可行的解决方案,对您的示例进行最少的更改。我确实将数据移动到模型中,并清理了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
                            }
                        }
                    }
                }
            }
        }
    }
}