0

我正在使用 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()支持项目似乎没有得到更新。因此,没有任何更新的值被打印到控制台。

我在这里做错了什么?

4

1 回答 1

1

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

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

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

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

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

val url = bind(MenuRoute::url)

您可以使用 TornadoFX IDEA 插件检查“将所有属性转换为 TornadoFX 属性”来自动修改您的属性。这会将您的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)

于 2017-05-25T21:04:44.290 回答