绑定属性不起作用

时间:2017-05-25 19:05:28

标签: javafx kotlin tornadofx

我使用TornadoFX 1.7.5并且我似乎无法使用绑定属性。我有以下ItemViewModels

class DynamicMenuViewModel : ItemViewModel<DynamicMenu>(DynamicMenu()) {
  val title = bind { item?.title?.toProperty() }
  val isBold = bind { item?.isBold?.toProperty() }
  val routes = bind { item?.routes?.toProperty() }
}
data class DynamicMenu(var title: String = "", var isBold: Boolean = false, var routes: MutableList<MenuRouteViewModel> = mutableListOf())

class MenuRouteViewModel : ItemViewModel<MenuRoute>(MenuRoute()) {
  val url = bind { item?.url?.toProperty() }
  val title = bind { item?.title?.toProperty() }
  val isBold = bind { item?.isBold?.toProperty() }
  val showNew = bind { item?.showNew?.toProperty() }
}
data class MenuRoute(var url: String = "", var title: String = "", var showNew: Boolean = false, var isBold: Boolean = false)

这样绑定:

//routesController.dynamicMenu is an instance of DynamicMenuViewModel()

textfield(property = routesController.dynamicMenu.title) {
  prefWidth = formWidth * .5
  gridpaneConstraints {
    columnRowIndex(0, 1)
    marginLeft = 10.0
    columnSpan = 2
    marginBottom = 20.0
  }
}

checkbox(property = routesController.dynamicMenu.isBold){
  gridpaneConstraints {
    columnRowIndex(2, 1)
    marginLeft = 15.0
    marginBottom = 20.0
  }
}

然后,当我单击按钮时,以下函数提交模型并将它们打印到屏幕:

  fun onClick(){
    commitModel()
    println(dynamicMenu.item.toString())
    dynamicMenu.item.routes.forEach {
      println(it.item.toString())
    }
  }

  fun commitModel(){
    dynamicMenu.item.routes.forEach {
      it.commit()
    }
    dynamicMenu.commit()
  }

问题在于,当我运行程序并编辑文本字段和复选框时,然后单击运行onClick()的按钮,支持项目似乎没有得到更新。因此,没有任何更新的值打印到控制台。

我在这里做错了什么?

1 个答案:

答案 0 :(得分:1)

您可能知道ViewModel只能双向绑定JavaFX属性。您的域对象不包含JavaFX属性,因此您需要转换它们。但是,您使用的toProperty()函数仅对值进行操作,并将其转换为属性。此属性无法知道它的字段所有者,因此无法写回域对象。

幸运的是,您可以使用observable函数使您的域对象属性也可写:

val url = bind { item?.observable(MenuRoute::url) }

由于observable函数对MenuRoute对象的特定实例进行操作,因此它现在有足够的信息在您commit()模型时写回该实例。

如果您考虑将域对象中的属性更改为可观察,则可以编写:

val url = bind(MenuRoute::url)

您可以使用TornadoFX IDEA插件检查&#34;将所有属性转换为TornadoFX属性&#34;自动修改您的属性。这会将您的MenuRoute对象转换为:

class MenuRoute {
    val isBoldProperty = SimpleBooleanProperty(false)
    var isBold by isBoldProperty

    val showNewProperty = SimpleBooleanProperty(false)
    var showNew by showNewProperty

    val urlProperty = SimpleStringProperty("")
    var url by urlProperty

    val titleProperty = SimpleStringProperty("")
    var title by titleProperty
}

(你必须手动删除你班上的data修饰符。还要注意插件的当前版本在转换函数中有一个错误,它会留下旧参数 - 新版本将很快发布)。

如果你因为各种原因不想这样做,我甚至能够支持这种优秀的语法,即使是像你这样的可变变量,所以从TornadoFX 1.7.6开始,你可以在绑定语句中使用这种语法即使您不想更改数据类:

val url = bind(MenuRoute::url)