For instance, properties defined on a JavaFX class have a distinct signature that is similar and at the same time alien, if compared to the JavaBean conventions followed by Java/Groovy, the following JavaFX Script class
when compiled with the current JavaFx 1.2 compiler produces the following bytecode signatures
As you can see the str variable has a getter/setter pair but the names are a bit different to what we are used to in Java/Groovy land, there is also an additional related field loc$str, which by my understanding, is what makes binding work. Another funny bit about loc$str is that it is lazy initialized, it usually is linked to str, but that can change depending on the access modifier set on str. In any case I think you agree that calling
from either Java or Groovy is not that pleasant, what about this
it looks like JavaFX Script code but it is actually Groovy code, FxBuilder makes sure to weave the necessary meta-magic for you, no need to dive into JavaFX's internals. Back to ObjectLocation, which makes binding tick, instances of that class may have listeners attached to them, but those listeners are not your typical PropertyChangelisteners so you're forced to attach a different type of listener: com.sun.javafx.runtime.location.ChangeListener. If the package name sends a red alert through your system you'll be correct, this is an internal construct, as a matter of fact it used to be called ObjectChangeListener and it had a simpler API. Well FxBuilder says "don't worry, I'll handle that complexity for you" by letting you register either a Closure or a PropertyChangeListener as you're used to
There are other useful bits of syntactic sugar and shortcuts:
- All FXObjects have
- location(String name) - returns an ObjectVariable identified by name
- hasLocation(String name) - does the object contain an attribute identified by name?
- locationType(String name) - returns the type of the ObjectVariable identified by name
- Sequences can be accessed using array subscript notation because they haven been enhanced with getAt(int).
- You can register Changelisteners directly to ObjectVariables using a closure, example: hw.location("str").onChange = { oldValue, newValue -> /*do something*/ }
Keep on Groovying!