Связывание модели предметной области с полями, допускающими значение NULL, в ItemViewModel

При запуске этого кода:

class PersonApp : App(PersonView::class)
class Person {
    var name: String? = null
}
class PersonModel: ItemViewModel<Person>() {
    val name = bind(Person::name)
}
class PersonView : View() {
    val model: PersonModel by inject()
    override val root = form {
        textfield(model.name)
    }
}

Выдается следующее исключение:

Nov 26, 2017 12:18:10 PM tornadofx.DefaultErrorHandler uncaughtException
SEVERE: Uncaught error
kotlin.TypeCastException: null cannot be cast to non-null type javafx.beans.property.Property<N>
    at favetelinguis.bfgx.PersonModel$$special$$inlined$bindMutableNullableField$1.invoke(ViewModel.kt:538)
    at favetelinguis.bfgx.PersonModel$$special$$inlined$bindMutableNullableField$1.invoke(ViewModel.kt:512)
    at favetelinguis.bfgx.PersonModel.<init>(Exeee.kt:27)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at tornadofx.FXKt.find(FX.kt:413)
    at favetelinguis.bfgx.Bree$$special$$inlined$inject$1.getValue(Component.kt:954)
    at favetelinguis.bfgx.Bree$$special$$inlined$inject$1.getValue(Component.kt:151)
    at favetelinguis.bfgx.Bree.getModel(Exeee.kt)
    at favetelinguis.bfgx.Bree$root$1.invoke(Exeee.kt:20)
    at favetelinguis.bfgx.Bree$root$1.invoke(Exeee.kt:17)
    at tornadofx.FXKt.opcr(FX.kt:454)
    at tornadofx.FormsKt.form(Forms.kt:23)
    at favetelinguis.bfgx.Bree.<init>(Exeee.kt:19)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at tornadofx.FXKt.find(FX.kt:413)
    at tornadofx.FXKt.find$default(FX.kt:398)
    at tornadofx.App.start(App.kt:79)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

Каков идиоматический способ работы с моделями предметной области, где все начальные значения равны нулю и должны быть установлены из графического интерфейса? Вот как я могу изменить приведенный выше код, чтобы он работал должным образом?


person user3139545    schedule 26.11.2017    source источник


Ответы (1)


Это уже должно работать в TornadoFX 1.7.13-SNAPSHOT, мы внесли некоторые улучшения в обнуляемые POJO. Альтернативный подход (и лучший IMO) заключается в использовании свойств JavaFX в объектах вашего домена:

class Person {
    val nameProperty = SimpleStringProperty()
    var name by nameProperty
}

И последнее, что нужно учитывать, это то, что вы не установили начальный элемент в свою ViewModel. Помните, что ViewModel сама не создает экземпляры вашего элемента, вы должны сделать это вручную или даже предоставить ViewModel элемент по умолчанию при его создании:

class PersonModel : ItemViewModel<Person>(Person()) {
    val name = bind(Person::name)
}
person Edvin Syse    schedule 26.11.2017