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

时间:2017-12-23 22:54:31

标签: tornadofx

我对Kotlon,JavaFX和Tornadofx都很陌生。我喜欢到目前为止看到的:) (也是Stackoverflow的新功能,我希望我没有把它拉得太远......

我有一个应用程序来检索远程JSON数据。编辑该数据并将其作为JSON返回给服务器。

可编辑的表格视图显示此数据(包含嵌套属性),侧面的编辑器也用于编辑。

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

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

  • 代码对我来说似乎过于多余。理想情况下,我想坚持使用数据类,但无法使用POJO进行编辑。
  • 此外,表格中使用嵌套地址属性的方式对我来说似乎有些偏差。其他数据类也会有地址,每次复制属性肯定都不好。
  • (该模型没有将更改写回POJO。我已经修改了SimpleStringProperty的修补版本,但我甚至不确定我使用它的方式是否是最好的方法。)

        package com.jadev.office
    
        import javafx.application.Application
        import javafx.beans.property.SimpleObjectProperty
        import javafx.beans.property.SimpleStringProperty
        import javafx.collections.FXCollections
        import javafx.geometry.Orientation
        import tornadofx.*
    
        // data classes obtained by parsing JSON from remote server, will be send back to the server to update the data
    
        // Address should be used in several other classes
        data class Address(var street: String, var city: String, var country: String)
    
        data class Person(var name: String, var address: Address)
    
        // Editable versions to use in table and editor view, this is wrapping the original data
        // to avoid duplicating the properties
        class EditableAddress(var address: Address) {
            var streetProperty = SimpleStringProperty(address, "street", address.street)
            var cityProperty = SimpleStringProperty(address, "city", address.city)
            var countryProperty = SimpleStringProperty(address, "country", address.country)
        }
    
        class EditablePerson(val person: Person) {
            val nameProperty = SimpleStringProperty(person, "name", person.name)
    
            val editableAddress = EditableAddress(person.address)
    
            val addressProperty = SimpleObjectProperty(editableAddress)
            val streetProperty = addressProperty.select(EditableAddress::streetProperty)
            val cityProperty = addressProperty.select(EditableAddress::cityProperty)
            val countryProperty = addressProperty.select(EditableAddress::countryProperty)
        }
    
        class PersonViewModel : ItemViewModel<EditablePerson>() {
            var name = bind(EditablePerson::nameProperty)
            var street = bind(EditablePerson::streetProperty)
            var city = bind(EditablePerson::cityProperty)
            var country = bind(EditablePerson::countryProperty)
        }
    
        val persons = mutableListOf(
                Person("Adam", Address("Paradise 1", "Eden", "ED")),
                Person("Eve", Address("Paradise 1", "Eden", "ED")))
    
        class MainView : View() {
            val editablePersons = FXCollections.observableArrayList<EditablePerson>(persons.map { EditablePerson(it) })
            val model: PersonViewModel by inject()
    
            override val root = splitpane(Orientation.HORIZONTAL) {
                tableview(editablePersons) {
                    column("Name", EditablePerson::nameProperty)
                    column("Street", EditablePerson::streetProperty)
                    column("City", EditablePerson::cityProperty)
                    column("Country", EditablePerson::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() {
                //for some reason this is updating the table but not the data wrapped by SimpleStringProperty()
                model.commit()
                println("Updated person: ${model.item.person}")
                println("Updated persons: ${persons}")
            }
        }
    
        class SampleApp : App(MainView::class)
    
        fun main(args: Array<String>) {
            Application.launch(SampleApp::class.java, *args)
        }
    

1 个答案:

答案 0 :(得分:0)

我确保始终只有一个域对象和该对象的相应ViewModel。我喜欢实现<RichTextBox x:Name="txt1" IsDocumentEnabled="True" HorizontalAlignment="Left" Height="183" Margin="36,10,0,0" VerticalAlignment="Top" Width="508"> <FlowDocument IsEnabled="True"> <Paragraph LineHeight="1"> <Button Content="Button" Height="25" Width="93" Click="Button_Click_1"/> </Paragraph> </FlowDocument> </RichTextBox> 并直接处理序列化/反序列化。我从未见过需要进行优化,因此我不会在不需要的地方使用可观察值,所以我只是坚持这种模式。

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

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

我确实喜欢你在人物视图模型中公开地址字段的想法,以便他们可以与人一起提交。我已经更改了您的申请以反映这些想法。

JsonModel