TornadoFX:绑定模型的正确方法

时间:2019-12-11 20:25:21

标签: javafx tornadofx

我正在看这个: tornadofx

并尝试通过数据库连接和更多选项进行扩展(并非所有选项都有意义,但它只是在沙箱中播放)。

即使表可以直接编辑并且数据将保留在数据库中,我也尝试通过文本字段进行编辑。实际的表编辑将通过不同的视图进行,而不是表本身,正如我所说的那样。 使用的数据库是Jetbrains Exposed。

    object Categories : IntIdTable() {
    val name = varchar("name", 64).uniqueIndex()
    val description = varchar("description", 128)
}

class Category(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<Category>(Categories)

    var name by Categories.name
    var description by Categories.description

    override fun toString(): String {
        return "Category(name=\"$name\", description=\"$description\")"
    }
}

现在控制器看起来像这样,功能只是基本功能,仅作为示例。

typealias ModelToDirtyState = Map.Entry<CategoryModel, TableColumnDirtyState<CategoryModel>>

class CategoryModel() : ItemViewModel<Category>() {
    val name: SimpleStringProperty = bind(Category::name)
    val description: SimpleStringProperty = bind(Category::description)
}


class DBController : Controller() {

    val categories: ObservableList<CategoryModel> by lazy {

        transaction {
            SchemaUtils.create(Categories)
            Category.all().map {
                CategoryModel().apply {
                    item = it
                }
            }.observable()
        }
    }

    init {
        Database.connect(
            "jdbc:mysql://localhost:3306/test", driver = "com.mysql.cj.jdbc.Driver",
            user = "test", password = "test"
        )

        TransactionManager.manager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE
    }

    fun deleteCategory(model: CategoryModel) {
        runAsync {
            transaction {
                model.item.delete()
            }

        }
        categories.remove(model)
    }

    fun updateCategory(model: CategoryModel) {
        transaction {
            Categories.update {
                model.commit()
            }


        }

    }



 fun commitDirty(modelDirtyMappings: Sequence<ModelToDirtyState>) {
        transaction {
            modelDirtyMappings.filter { it.value.isDirty }.forEach {
                it.key.commit()
                println(it.key)// commit value to database
                it.value.commit()   // clear dirty state
            }
        }
    }

只是为了快速地对控制器进行注释,删除方法按“预期”工作,但更新程序却不起作用,这在某种意义上不起作用,即使用删除项后既要从数据库又删除表视图(底层列表)本身,并且当我确实没有更新它,现在我知道了原因,我在数据库和列表上都手动调用了remove,现在进行更新也许我可以更改监听器,或者tornadofx可以为我做到这一点,我只是无法将其设置为做到这一点。以下代码将使事情变得更加清晰。

class CategoryEditor : View("Categories") {
    val categoryModel: CategoryModel by inject()
    val dbController: DBController by inject()
    var categoryTable: TableViewEditModel<CategoryModel> by singleAssign()
    var categories: ObservableList<CategoryModel> by singleAssign()


    override val root = borderpane {
        categories = dbController.categories

        center = vbox {
            buttonbar {
                button("Commit") {
                    action {
                        dbController.commitDirty(categoryTable.items.asSequence())
                    }
                }
                button("Roll;back") {
                    action {
                        categoryTable.rollback()
                    }
                }

//                This model only works when i use categorytable.tableview.selected item, if i use categoryModel, list gets updated but not the view itself
//                Question #1 how to use just categoryModel variable without need to use categorytable.tableview.selecteditem
                button("Delete ") {
                    action {
                        val model = categoryTable.tableView.selectedItem
                        when (model) {
                            null -> return@action
                            else -> dbController.deleteCategory(model)
                        }
                    }
                }

                //And here no matter what i did i could not make the view update 
                button("Update") {
                    action {

                        when (categoryModel) {
                            null -> return@action
                            else -> dbController.updateCategory(categoryModel)


                        }
                        categoryTable.tableView.refresh()

                    }
                }
            }
            tableview<CategoryModel> {
                categoryTable = editModel
                items = categories

                enableCellEditing()
                enableDirtyTracking()
                onUserSelect() {
                   //open a dialog
                }

                //DOES WORK
                categoryModel.rebindOnChange(this) { selectedItem ->
                    item = selectedItem?.item ?: CategoryModel().item

                }
//                Question #2. why bindSelected does not work, and i have to do it like above 
                //DOES NOT WORK
 //               bindSelected(categoryModel)
//
                column("Name", CategoryModel::name).makeEditable()
                column("Description", CategoryModel::description).makeEditable()
            }
        }
        right = form {

            fieldset {
                field("Name") {
                    textfield(categoryModel.name)
                }
            }
            fieldset {
                field("Description") {
                    textfield(categoryModel.description)
                }
            }
            button("ADD CATEGORY") {
                action {
                    dbController.addCategory(categoryModel.name.value, categoryModel.description.value)

                }
            }
        }
    }
}

我对大量代码表示歉意,在最后的代码中,我也以注释的形式留下了一些问题,但我未能达到预期的结果。  我确定我没有正确地绑定代码,我只是不明白为什么,我有时也使用一个变量来更新数据,我声明了一个“ categoryModel”,有时我使用了tableview.selecteditem,这似乎很hacky,我似乎无法掌握方式。

谢谢!

0 个答案:

没有答案