Future of Skins

John Hendrikx hjohn at xs4all.nl
Tue Jan 7 02:30:40 PST 2014

Hi List,

I'm wondering if Skins in their current form are "finished" or that more 
changes are still likely to come.  The Skin interface is public, and 
SkinBase is as well.  Unfortunately, it seems that even though SkinBase 
is treated differently by JavaFX from regular Skins, the opportunity was 
not used to give SkinBase an initialize method and make Skins truly 

The reason I'm asking is because I'm developing a control that would 
greatly benefit from customizable and switchable skins, which differs 
quite a bit from the use patterns I've seen so far for Controls in 
JavaFX (I don't think any of them has more than one Skin out of the 
box).  My control would need:

- Multiple different layouts, each with potentially different (CSS) 
properties to customize the chosen layout further (the properties would 
only make sense for the given layout (or skin)).
- Easy switching between different layouts
- Highly customizable (possibility to override methods in the layouts or 
provide custom code for certain parts of the rendering)

I've been looking into providing this with Skins, but I keep bumping 
into odd choices made, especially related to their resuability.  As far 
as I know, a Skin is created with a reference to the control it is 
supposed to Skin -- at this time the Skin (if it is a SkinBase) 
apparently has done all kinds of stuff to the control, whether setSkin 
is called or not.... ehr??  Then later you are supposed to call setSkin 
on the control with the newly created Skin... which is apparently an 
almost optional step, unless it is not a SkinBase...?

- What happens when I create the Skin but donot call setSkin?  --> 
Undefined, depends on whether or not it is extended from SkinBase (?)... 
SkinBase skins seem to make this step almost optional.
- What happens when I call setSkin on a different control with this 
Skin? --> Depends on whether or not SkinBase is extended.  Would break 
controls in most situations -- no check is done if getSkinnable matches 
- What happens when a disposed skin is setSkin'ned again? --> Seems to 
break most controls, no check is done if getSkinnable is null AFAICS.

This arrangement where the Skin class must be constructed with some 
parameter that must later match with the setSkin feels incredibly 
fragile to me.  It would be far nicer if a Skin was simply given an 
initialize method (which would also nicely match the dispose method) 
that takes the Skinnable as a parameter.  This initialization can be 
enforced in the setSkin method.  There is even a remark in the code 
about this:

                 // Note I do not remove any children here, because the
                 // skin will have already configured all the children
                 // by the time setSkin has been called. This is because
                 // our Skin interface was lacking an initialize method 
                 // and so the Skin constructor is where it adds listeners
                 // and so forth. For SkinBase implementations, the
                 // constructor is also where it will take ownership of
                 // the children.

Would it not have been a better idea to add an #initialize method to 
SkinBase if the code has two paths for "legacy" Skins and SkinBase skins 
anyway?  Or a Skin2 interface with the extra method + instanceof check?  
Or Java8 default #initialize method which does nothing by default?

Any of those would open up Skins to be far easier to use by making them 
reusable.  I really want to be able to do something like this:

     ComboBox<Skin> comboBox = new 
         new Skin1(),
         new Skin2(),
         new Skin3(),
         new SubClassOfSkin1(Color.RED)),
         new Skin2() {
            // with some methods overriden

Then bind those simply with:


This would allow a ComboBox to control the Skin of another Control, 
because skins are reusable AND donot require knowledge of the control 
they are Skinning at construction time.  This is currently not possible 
without creating somekind of SkinFactory and a ChangeListener on the 
ComboBox that does something like:


This problem gets worse when you also want to customize the Skins a 
bit.  All the customization must be done in the SkinFactory part, every 
time the Skin is switched.  With reusable skins, they can just be 
configured once.

So I'm left with a bit of a choice.  Do I make multiple Skins and a 
bunch of Factories?  Or do I simply create just one fixed Skin that just 
delegates everything it does to a second light-weight Skinning mechanism 
that is easier to switch, customize and extend?


More information about the openjfx-dev mailing list