我正在使用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只是左侧的一个表格,右侧的一个表格:
代码是:
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")
}
目前,我发现我花了几个小时但无法解决的几个问题:
false
,因此reset
按钮始终处于禁用状态reset
按钮,则无法将表单数据重置为原始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
。但是我不确定这是否是最佳解决方案。
代码也在上面的演示仓库中更新。