如何修改以数据数组为行的表视图中的行?

时间:2018-07-24 16:42:14

标签: kotlin tornadofx

我正在使用TornadoFX编写表演示,当我们从数据库中检索ResetSet时,它可以基于ResultSet显示列和行。

数据库部分不在此问题范围内,因此我只是将数据硬编码为:

private val columnNames = listOf("Id", "Name")

private val data = FXCollections.observableArrayList<List<Any>>(
        mutableListOf(111, "AAA"),
        mutableListOf(222, "BBB"),
        mutableListOf(333, "CCC"),
        mutableListOf(444, "DDD")
)

并使用ViewModel保留选定的行数据:

class RowModel(row: List<Any>) : ViewModel() {
    val backingValue = SimpleObjectProperty(row)
}

然后,UI只是左侧的一个表格,右侧的一个表格:

table

代码是:

class HelloWorld : View() {

    private val emptyRow = emptyList<Any>()
    private val model = RowModel(emptyRow)

    private lateinit var table: TableView<List<Any>>

    override val root = hbox {
        vbox {
            tableview(data) {
                table = this
                columnNames.forEachIndexed { index, name ->
                    column<List<Any>, String>(name) { it.value[index].toString().toProperty() }.minWidth(100)
                }
                model.rebindOnChange(this) { selectedRow ->
                    backingValue.value = selectedRow ?: emptyRow
                }
            }
            hbox {
                button("New Row").setOnAction {
                    model.rebind { backingValue.value = emptyRow }
                }
                button("Delete selected").setOnAction {
                    data.remove(table.selectedItem)
                }
            }
        }
        vbox {
            form {
                fieldset {
                    textProperty.bind(formName())
                    columnNames.forEachIndexed { index, name ->
                        field(name) {
                            textfield().bind(model.backingValue.map { it.getOrNull(index)?.toString() ?: "" })
                        }
                    }
                    field(forceLabelIndent = true) {
                        button("Rest") {
                            enableWhen(model.dirty)
                            action { model.rollback() }
                        }
                        button("Save") {
                            // enableWhen(model.dirty)
                            action {
                                model.commit()
                                if (isNewRow().value) {
                                    data.add(model.backingValue.value)
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private fun isNewRow(): BooleanBinding {
        return Bindings.createBooleanBinding({ !data.contains(model.backingValue.value) }, arrayOf(model.backingValue))
    }

    private fun formName(): StringBinding = Bindings.`when`(isNewRow()).then("New").otherwise("Modify")
}

目前,我发现我花了几个小时但无法解决的几个问题:

  1. 脏检查始终返回false,因此reset按钮始终处于禁用状态
  2. 如果启用reset按钮,则无法将表单数据重置为原始
  3. 单击save按钮时,它无法更新左侧表格中的数据。

需要您的帮助,谢谢!

还提供了一个完整的演示项目:https://github.com/javafx-demos/tornadofx-table-crud-with-data-array-demo

更新

我有一个解决方案,方法是创建一个RowBean以将数组列表包装为JavaBean,并为每个单元格提供一个属性:

class RowBean(row: ArrayList<String>) {
    val rowProperty = SimpleObjectProperty(row)
    fun cellProperty(index: Int): SimpleStringProperty = SimpleStringProperty(this.rowProperty.value[index]).apply {
        Bindings.bindBidirectional(this, rowProperty, object : StringConverter<ArrayList<String>>() {
            override fun toString(obj: ArrayList<String>?): String {
                return obj?.get(index) ?: ""
            }

            override fun fromString(string: String?): ArrayList<String> {
                val newList = Lists.copy(rowProperty.value)
                newList[index] = string
                return newList
            }
        })
    }
}

然后将其用作普通的JavaBean,并照常使用ViewModel。但是我不确定这是否是最佳解决方案。

代码也在上面的演示仓库中更新。

0 个答案:

没有答案