Tornadofx:如何减少 table+数据编辑器 类 中的冗余?

Tornadofx: How can I reduce redundancy in table+editor of data classes?

我对 Kotlon、JavaFX 和 Tornadofx 还很陌生。我喜欢我目前所看到的 :) (也是 Whosebug 的新手,我希望我没有把它拉得太远......

我有一个应用程序可以检索远程 JSON 数据。该数据被编辑并作为 JSON.

返回到服务器

editable table 视图显示此数据(包含嵌套属性),旁边的编辑器也用于编辑。

我附上了一个示例应用程序来演示这一点。这对我来说似乎很多余而且太复杂了。我想这里一定有问题:)

感谢您提供的任何指导/帮助! :)

我确保始终只有一个域对象和该对象对应的 ViewModel。我也喜欢直接在那里实现 JsonModel 和处理 serialization/deserialization。我从未见过优化的必要性,因此我不会在不需要的地方使用可观察值,所以我只是坚持这种模式。

确保每个对象都有一个 noargs 构造函数也是一个好主意,这样它们就可以在不调用专门构造函数的情况下被实例化。

您应该避免在对象的不同版本之间进行转换,如您所见,您只会 运行 陷入麻烦和细微的错误中。相反,我直接在 TableView 中对地址进行对象遍历。不是最漂亮的代码,但是更透明

不过,我确实喜欢您在人员视图模型中公开地址字段的想法,以便它们可以与人员一起提交。我已经更改了您的应用程序以反映这些想法。

import javafx.beans.property.SimpleObjectProperty
import javafx.beans.property.SimpleStringProperty
import javafx.geometry.Orientation
import tornadofx.*

class Person() {
    val nameProperty = SimpleStringProperty()
    var name by nameProperty

    val addressProperty = SimpleObjectProperty<Address>()
    var address by addressProperty

    constructor(name: String, address: Address): this() {
        this.name = name
        this.address = address
    }

    override fun toString() = "$name - $address"
}

class Address() {
    val streetProperty = SimpleStringProperty()
    var street by streetProperty

    val cityProperty = SimpleStringProperty()
    var city by cityProperty

    val countryProperty = SimpleStringProperty()
    var country by countryProperty

    constructor(street: String, city: String, country: String) : this() {
        this.street = street
        this.city = city
        this.country = country
    }

    override fun toString() = "$street, $city, $country"
}

class PersonModel : ItemViewModel<Person>() {
    val name = bind(Person::nameProperty)
    val address = bind(Person::addressProperty)

    val street = address.select(Address::streetProperty)
    val city = address.select(Address::cityProperty)
    val country = address.select(Address::countryProperty)
}

// The data would probably come from a controller in a real app
val persons = mutableListOf(
        Person("Adam", Address("Paradise 1", "Eden", "ED")),
        Person("Eve", Address("Paradise 1", "Eden", "ED"))).observable()

class MainView : View() {
    val model: PersonModel by inject()

    override val root = splitpane(Orientation.HORIZONTAL) {
        tableview(persons) {
            column("Name", Person::nameProperty)
            column<Person, String>("Street", { it.value.addressProperty.value.streetProperty })
            column<Person, String>("City", { it.value.addressProperty.value.cityProperty })
            column<Person, String>("Country", { it.value.addressProperty.value.countryProperty })

            bindSelected(model)
        }

        form {
            fieldset {
                label("Name:")
                textfield(model.name)

                label("Street:")
                textfield(model.street)

                label("City:")
                textfield(model.city)

                label("Country:")
                textfield(model.country)
            }

            button("Save") {
                action {
                    save()
                }
            }
        }
    }

    fun save() {
        model.commit()
        println("Updated person: ${model.item}")
        println("Updated persons: $persons")
    }
}

class SampleApp : App(MainView::class)

fun main(args: Array<String>) {
    launch<SampleApp>(args)
}