Event when CSS is applied

Tomas Mikula tomas.mikula at gmail.com
Wed Feb 18 08:10:00 UTC 2015

In case this information was buried in the previous email, maybe all
you need to better understand the problem is that layout() works
roughly* like this:

public final void layout() {
    for(Node child: getChildren()) {

layoutChildren() just resizes and positions child nodes (only direct
children), it does not call layout() on them.
You do not (usually) call layout() directly, it is called on the root
node in the layout pass. Neither can you override layout(), it is

* In reality, it first checks whether layout is needed at all. Also,
it only calls layout() on children that are Parents (other Nodes do
not have that method). And there's another piece that prevents
recursive calls to layout() on the same node.

On Wed, Feb 18, 2015 at 2:34 AM, Tomas Mikula <tomas.mikula at gmail.com> wrote:
> OK, so the major problem I see is that a lot of layout is done outside
> layoutChildren, using code like this:
> needlePane = new Pane();
> needlePane.widthProperty().addListener( (observable) -> {
>     drawNeedlePane();
> });
> What I think should be done is, instead of trying to hack around Pane,
> create class NeedlePane that extends Region and overrides
> layoutChildren. It would create its children in the constructor (or
> take them as constructor parameters), add them to its children list
> right in the constructor and never clear them, and position them on
> the layout pass (i.e. in layoutChildren).
> The problem you have (or one of the problems) is that in the layout
> pass, when lStackPane sets the size of needlePane, drawNeedlePane() is
> triggered which clears needlePane's children (this is shortly after
> the CSS was applied to them, just before the layout pass that is
> currently in progress), then adds them quickly back, but without CSS
> applied.
> Another problem is that in Skin's layoutChilren, you are trying to
> layout grand-grand-children. You should only be laying out direct
> children. The code reads
> protected void layoutChildren(double arg0, double arg1, double arg2,
> double arg3) {
>     super.layoutChildren(arg0, arg1, arg2, arg3);
>     setValueText();
>     scaleValueText();
>     positionValueText();
> }
> This is what it does:
> super.layoutChildren() resizes and positions lStackPane. It does not
> call layout() on it yet.
> The rest of the methods are positioning grand-children of that lStackPane.
> When the layoutChildren call returns, layout() will be called on all
> children, i.e. on lStackPane. Within lStackPane.layout(),
> lStackPane.layoutChildren() is called, which sets the width and height
> of needlePane, which triggers drawNeedlePane() (if size changed),
> which clears the children and adds them back. When
> lStackPane.layoutChildren() returns, needlePane.layout() is called,
> within which needlePane.layoutChildren() is called. This is where you
> should do the layout for valueText.
> Hope this helps.
> Tomas
> On Wed, Feb 18, 2015 at 1:46 AM, Tom Eugelink <tbee at tbee.org> wrote:
>> Sure! I'm very curious what can be done better.
>> https://github.com/JFXtras/jfxtras-labs/blob/8.0/src/main/java/jfxtras/labs/internal/scene/control/skin/gauge/linear/SimpleMetroArcGaugeSkin.java
>> You can also checkout the sources, you should be able to run
>> SimpleMetroArcGaugeTrial1.java without any other dependencies. Some of the
>> other classes will have compilation errors, but the gauge should run.
>> Tom
>> On 17-2-2015 23:15, Tomas Mikula wrote:
>>> Maybe if you can post the relevant part of your layoutChildren method
>>> so that others can look if they can suggest an improvement.
>>> Tomas
>>> On Tue, Feb 17, 2015 at 5:05 PM, Tom Eugelink <tbee at tbee.org> wrote:
>>>> On 17-2-2015 20:01, David Grieve wrote:
>>>>> On 2/17/15 1:30 PM, Tom Eugelink wrote:
>>>>>> The control is a codewise polish up one of Gerrit's gauges (with
>>>>>> permission!) and pulled into JFXtras (with tests and all). For an idea
>>>>>> on
>>>>>> what we are talking about:
>>>>>> https://www.youtube.com/watch?v=RH5X1uBu1d8
>>>>>> The process of centering the Text in that circle is a bit more complex.
>>>>>> 1. The value may vary between a min and max value.
>>>>>> 2. I want the Text to automatically utilize the maximum available
>>>>>> space,
>>>>>> but not change size when a longer or shorter text is shown.
>>>>>> To do this I have two additional Text nodes that have the same styling
>>>>>> as
>>>>>> the Text node (so these are on the scene, but not visible, otherwise
>>>>>> CSS is
>>>>>> not applied). These two text nodes get the maximum and minimum possible
>>>>>> value set. Then on these two some pythagoras is applied and in that way
>>>>>> one
>>>>>> can determine the scale factor so that the value will never be rendered
>>>>>> outside of the circle. Then the actual to-be-rendered value can be
>>>>>> placed
>>>>>> into the Text node and positioned in the centre of the circle.
>>>>>> The problem is that a lot of these calculations depend on the CSS
>>>>>> styling. What font is set? Bold or not? So I can only do these
>>>>>> calculcation
>>>>>> after the CSS has been applied. This unfortunately is not yet the case
>>>>>> when
>>>>>> the skin is instantiated. This means that if I do not used the
>>>>>> layoutChildren, the initial presentation is totally off, untill the
>>>>>> first
>>>>>> min/max/value is set.
>>>>> Have you looked at the javadoc for Node#applyCss()?
>>>> I did just now and tried calling that and layout when the skin is being
>>>> instantiated, but apparently things are not setup right yet.
>>>> Maybe layoutChildren with bound checking is the way to go.

More information about the openjfx-dev mailing list