Связанные свойства не работают

Я использую 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() , элемент резервного копирования, похоже, не обновляется. Поэтому ни одно из обновленных значений не выводится на консоль.

Что я здесь делаю неправильно?

ViewModel может, как вы, вероятно, знаете, только привязать двунаправленно к свойствам JavaFX. Объекты домена не содержат свойств JavaFX, поэтому вам необходимо их преобразовать. Однако toProperty() вы используете, работает только по значению и превращает ее в свойство. Это свойство не имеет никакого представления о его владельце поля и, следовательно, не может записать обратно в объект домена.

К счастью, вы можете использовать observable функцию, чтобы сделать ваши свойства объекта домена доступными для записи:

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

Поскольку observable функция работает с конкретным экземпляром объекта MenuRoute , теперь у нее достаточно информации для записи обратно в этот экземпляр, когда вы commit() модель.

Если вы рассмотрите возможность изменения свойств объектов домена для наблюдения, вы можете написать:

val url = bind(MenuRoute::url)

Вы можете использовать инспекцию плагина TornadoFX IDEA «Преобразовать все свойства в TornadoFX Properties», чтобы автоматически перерабатывать ваши свойства. Это превратит ваш объект 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 вы можете использовать этот синтаксис в своих заявлениях о привязке, даже если вы не знаете, t хотите изменить свои классы данных:

val url = bind(MenuRoute::url)