Views
8 months ago

tornadofx-guide

Property Delegates

Property Delegates create a function that fetches the Property from TornadoFX and returns it. class Bar { var foo by property() fun fooProperty() = getProperty(Bar::foo) } Especially as you start working with TableView and other complex controls, you will likely find this pattern helpful when creating model classes, and this pattern is used in several places throughout this book. Note you do not have to specify the generic type if you have an initial value to provide to the property. In the below example, it will infer the type as `String. class Bar { var foo by property("baz") fun fooProperty() = getProperty(Bar::foo) } Alternative Property Syntax There is also an alternative syntax which produces almost the same result: import tornadofx.getValue import tornadofx.setValue class Bar { val fooProperty = SimpleStringProperty() var foo by fooProperty } Here you define the JavaFX property manually and delegate the getters and setters directly from the property. This might look cleaner to you, and so you are free to choose whatever syntax you are most comfortable with. However, the first alternative creates a JavaFX compliant property in that it exposes the Property via a function called fooProperty() , while the latter simply exposes a variable called fooProperty . For TornadoFX there is no difference, but if you interact with legacy libraries that require a property function you might need to stick with the first one. Null safety of Properties By default properties will have a Platform Type with uncertain nullability and completely ignore the null safety of Kotlin: 192

Property Delegates class Bar { var foo by property() fun fooProperty() = getProperty(Bar::foo) val bazProperty = SimpleStringProperty() var baz by bazProperty init { foo = null foo.length // Will throw NPE during runtime } } baz = null baz.length // Will throw NPE during runtime To remedy this you can set the type of your property on the var (not on the Property-Object itself!). But keep in mind to set a default value on the property object when you set the var to be nullable or you will get an NPE anyways: class Bar { var foo:String by property("") // Non-nullable String with default value fun fooProperty() = getProperty(Bar::foo) val bazProperty = SimpleStringProperty() // No default needed var baz: String? by bazProperty // Nullable String init { foo = null // Will no longer compile foo.length } } baz = null baz.length // Will no longer compile FXML Delegate If you have a given MyView View with a neighboring FXML file MyView.fxml defining the layout, the fxid() property delegate will retrieve the control defined in the FXML file. The control must have an fx:id that is the same name as the variable. Now we can inject this Label into our View class: 193

GUIDE
GUIDE
Guide
GUIDE
Guide
GUIDE
GUIDE
Guide
GUIDE
Guide
Guide
GUIDE
GUIDE
GUIDE
GUIDE