Tornadofx: Poor documentation on properties and binding

Created on 9 Jan 2021  路  7Comments  路  Source: edvin/tornadofx

Hi there!

I've been working on a solo tornadofx project for a little while now, and something that still escapes me is the interaction of binding and properties.

I've trawled all the tornadofx and javafx guides, docs, and tutorials that I can find, and guidance on how binding works seems to be entirely missing.

The only two types of guidance I can find are either

  • The most straightforward binding of one property to a field; useful, but doesn't really explain what's going on, and no guidance for anything even a little more complex
  • Raw API docs and/or reading source code, both of which are only really useful to people who have a decent grasp on the concepts already.

I'd be happy to write up a page for the guide and submit it as a PR, but could someone talk me through what's going on with properties and binding in tornadofx/javafx?

Most helpful comment

We are waiting for questions. It will not be superfluous to improve the documentation

All 7 comments

do you need information about the inner workings of properties and binding? Or from an API point of view?

It's more an idea of developing a greater understanding in new users so they can apply the principles to their own situations. Right now the docs have good descriptions of how to do certain things, and good justifications for why you should do it, but not much of how using properties and bindings achieve that, or what to do outside of forms.

Let me write up some questions/topics, probably easier to answer than my original generic question.

We are waiting for questions. It will not be superfluous to improve the documentation

OK so the general areas I'd like to be able to cover in documentation are (not necessarily in this order):

  • Where does JavaFX end and TornadoFX begin? Where should we be relying on JavaFX docs instead of TornadoFX docs?
  • What's the distinction between fields, properties, bindings, and observables?
  • What's the practical difference between model.nameProperty(), Model::nameProperty, etc?
  • What's the reasoning for properties existing in general? [I think there's one or two decent JavaFX pages on this]
  • How do you bind distinctly different types of things? Like if you have a boolean on a model and want
    a view to show a border if the boolean is true? Is that even an appropriate use of binding?
  • More generally; when should we use bindings vs listeners?
  • When should we pass around bindings vs properties?
  • How do we bind multiple properties of a node to multiple properties of a model? [answered here: #1305]
  • How do we best approach derived/combined properties?
    e.g. if I have Double properties x and y, and I want a String property "Coordinates: $x,$y",
    how best do we handle that? Is there a form of property suitable for that? We can use stringBinding but that creates a binding. What if we want to do something different if x and/or y are null?
  • Corollary, what's the best approach for indicating that these derived properties are read-only? ReadOnly[Thing]Wrappers?
  • Being able to provide more examples of these would be helpful as well, as there's often slightly confusing
    scope to certain function calls, e.g. stringBinding(x, y) { "Coordinates: $x,$y" } is a bit magic.
  • How do we handle modifying collections of things? bindChildren I assume but this isn't in the documentation, and there's
    also no end-to-end example of CRUD with forms, only the static index, part-static show, part update, no create, no delete, no modifying the list of items.
  • When is it appropriate to have multiple instanced viewmodels, vs a singleton that you rebind?
  • How do we best handle nullable properties? I found it quite difficult to do any binding to a property on something that
    might be null, or deriving from possibly null properties.

That's about all I can think of for now.

I could answer a couple of questions now, but I will still answer in a couple of days. Just note that property :: name is Kotlin (I'll answer in detail later), and tornadofx leash wraps javafx, it doesn't add anything in terms of Property

1 Where does JavaFX end and TornadoFX begin? Where should we be relying on JavaFX docs instead of TornadoFX docs?

tornadofx has no properties of its own (except https://tornadofx.io/dokka/tornadofx/tornadofx/-sorted-filtered-list/index.html). Framework is essentially a wrapper, it only adds functions for more convenient construction

2 What's the distinction between fields, properties, bindings, and observables?

What is field and property - it is necessary to go to the dock of Kotlin. You also need to understand that there are properties of Kotlin (KProperty) and properties of JavaFx (Property).

field is just a class field.
property - encapsulates some property of an object, this can be a wild or a calculated value.
property javafx or observable property - object properties that can have listeners that handle property value updates.
Properties are divided into mutable (see Property, WritableValue) and ReadOnlyProperty .Properties are changed either by you or by other components. It has setValue, ReadOnlyProperty - may have internal logic to change .
binding - see https://docs.oracle.com/javase/8/javafx/api/javafx/beans/binding/Bindings.html. are needed when you need to calculate values from other observable properties. Changes will occur when one of the properties changes its value.

properties notify of changes using the invalidate function.

3 What's the practical difference between model.nameProperty(), Model::nameProperty, etc?

this is doc kotlin https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-property/, https://kotlinlang.org/docs/reference/reflection.html#property-references.

val javafxProperty = model.nameProperty() // will return `Property`
val kProperty = model.Model::nameProperty // will return `KProperty`, 

javafxProperty.value = value 

4 What's the reasoning for properties existing in general? [I think there's one or two decent JavaFX pages on this]

I didn't understand what I mean.

5 How do you bind distinctly different types of things? Like if you have a boolean on a model and want
a view to show a border if the boolean is true? Is that even an appropriate use of binding?

Yes. There are different use cases, but they all rely on ChangeListener or InvalidationListener, see https://github.com/edvin/tornadofx/blob/master/src/main/java/tornadofx/Nodes.kt#L1070

6 More generally; when should we use bindings vs listeners?

if you have the result of calculations and you need to transfer it to other places (for example, in several nodes), then you need to use bindings. A classic example is summations, quantity displays are all bindings

7 When should we pass around bindings vs properties?

See at answer number 2

8 How do we bind multiple properties of a node to multiple properties of a model? [answered here: #1305]

need an extended answer?

9 How do we best approach derived/combined properties?
e.g. if I have Double properties x and y, and I want a String property "Coordinates: $x,$y",
how best do we handle that?

Bindings

9.1 Is there a form of property suitable for that? We can use stringBinding but that creates a binding.

they are needed for this

9.2 What if we want to do something different if x and/or y are null?

this is handled in the lambda used in the Binding.. Also note that for primitive properties (IntProperty, DoubleProperty etc), the value will never be null

10 Being able to provide more examples of these would be helpful as well, as there's often slightly confusing
scope to certain function calls, e.g. stringBinding(x, y) { "Coordinates: $x,$y" } is a bit magic.

lambda expressions are applied here. Documentation: https://kotlinlang.org/docs/reference/lambdas.html
code: https://github.com/edvin/tornadofx/blob/master/src/main/java/tornadofx/Properties.kt#L705

11 How do we handle modifying collections of things? bindChildren I assume but this isn't in the documentation, and there's
also no end-to-end example of CRUD with forms, only the static index, part-static show, part update, no create, no delete, no modifying the list of items.

This is where tornadofx ends and JavaFX begins. tornadofx only supplements with convenient functions.
There are different listeners for different types: properties, lists, map

12 Corollary, what's the best approach for indicating that these derived properties are read-only? ReadOnly[Thing]Wrappers?

You yourself choose, depending on what you need. This is usually ReadOnlyProperty. I advise you to take a look at how nodes are implemented. Read袨nlyProperty - does not have a default implementation, but you can explicitly specify the type, and create a regular property (SimpleProperty)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ThraaxSession picture ThraaxSession  路  3Comments

MairwunNx picture MairwunNx  路  8Comments

arslancharyev31 picture arslancharyev31  路  7Comments

pavan-p picture pavan-p  路  3Comments

jagiellonczyk14 picture jagiellonczyk14  路  6Comments