- Loading...
...
Controls follow the classic MVC design pattern. The Control is the "model". It contains both the state and the functions which manipulate that state. The Control class itself does not know how it is rendered or what the user interaction is. These tasks are delegated to the Skin ("view"), which may internally separate out the view and controller functionality into separate classes, although at present there is no public API for the "controller" aspect.
All Controls extend from the Control class, which is in turn a Region, which is a Node. Every Control has a reference to a single Skin, which is the view implementation for the Control. The Control delegates to the Skin the responsibility of computing the min, max, and pref sizes of the Control, the baseline offset, and hit testing (containment and intersection). It is also the responsibility of the Skin, or a delegate of the Skin, to implement and respond to all relevant key events which occur on the Control when it contains the focus.
Control extends from Region, and as such, is not a leaf node. From the perspective of a developer or designer the Control can be thought of as if it were a leaf node in many cases. For example, the developer or designer can consider a Button as if it were a Rectangle or other simple leaf node.
...
Whilst we were ready to make SkinBase public API in JavaFX 8.0 we had to unfortunately backtrack from our intentions to also provide an API to allow for easy handling of mouse and key events in JavaFX 8.0. The primary reason was that this becomes increasingly complex the more you look into it, especially if you start to think of behaviors as more than just internal control mappings but rather internal and external mappings between inputs and actions. Additionally, there is a need to consider exposing API that can read these mappings and to know what mappings are available for a given control (for Scene Builder to expose this functionality to developers, for example). The Jira issue tracking this feature can be found at RT-21598.
A JavaFX UI control has a relatively well-defined life cycle (except perhaps in its final stages of disposal, which I'll cover below). In short, a UI control goes through the following stages during its life:
At this point the control might have a skin. In summary, the order of precedence is that the controls user agent style sheet has highest priority, then the default user agent style sheet provided by JavaFX, and finally the result of a call to createDefaultSkin(). If the skin is null, an error message is logged, but the control is not prevented from being otherwise functional.
On the other side of the coin, disposal of a UI control is not so well-defined, as there is no hook in Control to listen for when it is no longer necessary to be kept alive. Despite this, there is the Skin.dispose() method that must be implemented by all implementations. Hopefully in the future a proper hook will be made such that dispose() will be called, but at present this is not the case.
UI controls depend on reflection when instantiating skins specified via the CSS -fx-skin property. The reflection code can be found in Control.loadSkinClass(). This method works by attempting to load a skin of the given class name, assuming it has a constructor that accepts a Control, and is able to be cast as a Skin<?>.