The 1.3 release of JavaFX is a huge on. Many things have been improved. Also some incompatible API changes occured.
Creating Custom controls has been really hard in 1.2. I have created a template that did what it should. But with the 1.3 release this template does no longer work.
So here we go and look at the issues related to custom controls one more time…. It is the same setup: The custom control is placed within a Stack.
Empty control
We start with an empty control without a skin. The result is the same as in 1.2: Everything is 0.
Simple Control with and empty Skin
Now we create a control and assign an empty skin. This is done within the init-block since createNode no longer exists. This results in the same behavior as in 1.2: There are hard coded values for prefWidth/height that are queried by the stack, set as width/height of the custom control and reflected by the layoutBounds. The boundsInLocal are still (0/0/0/0).
The Stack implementation has been changed. In 1.2 the Stack resized all nodes that implement Resizable to fill the available space. The default behaviour in 1.3 is to use the prefWidth/height.
The old behavior can be achieved by overwriting getHFill()/getVFill.
Skin containing just a Rectangle
The skin returns a Rectangle {widht:70 height:150}. The layoutBounds are not affected in any way. But the boundsInLocal are bound to the bounds of the node.
The result looks different than in 1.2: But just because the control is not resized! As a result the rectangle is drawn somewhere near the middle (but not in the middle). The position of the upper left border of the rectangle is placed by the Stack using the layoutBounds (drawn in red) as initial value for calculation.
So the result might be a little bit “dangerous”: For skins that have boundsInLocal that are near the hard coded values for prefWidth/height (and therefore width/height and therefore layoutBounds) the layout might be “good enough”. So the missing connection between width/height and boundsInLocal could be overlooked…
Skin with prefWidth/Height methods
The implementation of the prefWidth/Height methods is crucial – as written before. It has the expected results: The width/height of the control (and as result the layoutBounds) are changed accordingly by the container.
Connecting the width/height of the rectangle
As written before it is necessary to bind the width/height of the rectangle to the width/height of the control. When this is done the result looks as expected.
Conclusion
Creating custom controls in JavaFX is still quite difficult. And the documentation is still very poor. The template has to be changed slightly (due the removal of the create method). I will do this after the weekend.
The default of the Stack has been changed (and I like that). So it uses the prefWidth/Height per default. While this is the better behavior (imho) it might hide the fact that you have forgotten to implement the getPrefWidth/Height methods.
Please Oracle: Make those methods abstract asap!