Layout issue

Tomas Mikula tomas.mikula at
Wed Feb 12 08:07:38 PST 2014

Hi John,

I'm replying to your question from JIRA:

> Is there perhaps a better place to hook into when you want to have a
> chance to update the layout as a result of deferred property changes?

I took your example and modified it:

Perhaps look at the diff to see the changes I made:

Advantages of this solution:
  (+) no calls requestLayout() or applyCss();
  (+) no need to override layoutChildren() or compute*() methods.

  (-) adds a dependency on the ReactFX library
    (-) which requires JDK8

The main idea of this solution is this:
  1. you have an observable boolean value (beingUpdated in the
example) that you set to true while changes to you TreeListPane are
being performed and set to false when you are done with changes.
  2. the changes you perform may mark the layout as invalid
(treeInvalidations.push(null); in the example).
  3. whenever updating finishes (beingUpdated changes to false), you
do the layout (buildTree()), but only if the layout has been
    buildTreeImpulse = emit(treeInvalidations).on(beingUpdated.offs());
    buildTreeImpulse.subscribe(impulse -> buildTree());

You could recreate this pattern without ReactFX, I just find it
convenient to use event streams for the job.


On Wed, Feb 12, 2014 at 11:34 AM, John Hendrikx <hjohn at> wrote:
> On 11/02/2014 21:09, Martin Sladecek wrote:
>> The rule of thumb in case you modify content during the layout is that
>> content should depend on layout pane size, not the other way around. It
>> means that changing the content won't modify the min/pref/max size of the
>> pane as that would trigger another layout pass (possibly falling into a
>> loop).
> BorderPane
>   +- (TOP) Filter (subclass of FlowPane)
>   +- (CENTER) TreeView
> I modify the content during the compute* method of the BorderPane.  For
> TreeView I change the root; for the Filter (FlowPane) I add/remove children.
> For some reason that seems to be the "wrong" time to do it, despite the fact
> that this happens almost as the first thing during the layout process.
> LayoutChildren will get called later on BorderPane, and no more changes were
> made, and the layout is incorrect.  Then when the focus changes, the
> compute* methods get called again (but I change nothing since everything is
> valid still) and layoutChildren gets called again on BorderPane... and then
> everything looks correct.
>> This is why it's not recommended to change children during the layout, as
>> default computation of min/pref/max size depends on the children. But if you
>> modify compute* methods and return something that is not dependent on the
>> children, you can safely modify them while doing the layout.
>> So, e.g. your filter control might return pref size that is approx. for
>> 2-3 "tabs" (or whatnot). Since BorderPane resizes top to the full width, you
>> would always get the maximum width you can get. Based on the assigned width,
>> you can then compute the layout and add as much tabs as you can. Since that
>> would not change the pref width, the layout is done.
> It is actually a FlowPane -- I'd like it to accomodate the tabs as well as
> possible, and even add an extra row if they don't all fit.  Since I donot
> myself override its compute* methods, I didn't think the issue might be in
> that area (see the Filter class included in the JIRA I created -- it's
> really simple).
>> Anyway, as Jonathan already noted, a JIRA issue with some sample would be
>> great.
> Yes, I just did, RT-35830 has a nice sample.
> Thanks for giving some more insight in the layout process.
> --John
>> Thanks,
>> -Martin
>> On 02/11/2014 05:50 PM, John Hendrikx wrote:
>>> From an earlier posting on this list, I came to understand that in JavaFX
>>> 8 it is no longer allowed to modify the children list in layoutChildren, and
>>> that such modifications may need to be moved to the computerPref* methods.
>>> However, I get a different odd issue, and I'm wondering exactly what is
>>> allowed and what isn't when it comes to layout (any documentation on this?)
>>> What's happening is the following:
>>> I got a (subclass of) BorderPane, at the top I have a tab-like control
>>> (let's call it a FilterControl).  At the center I got a TreeView.
>>> When the BorderPane gets laid out, I set up the content for both the
>>> TreeView and the FilterControl.  I do this in layoutChildren or in
>>> computerPref* of the BorderPane -- it makes no difference. Setting up the
>>> content for the FilterControl involves changing its children list.  The
>>> TreeView probably will do the same (adding/removing Cells as needed).
>>> Now, I'm seeing layout issues.  The BorderPane for example is often
>>> putting the TreeView right on top of the FilterControl (stuff is
>>> transparent, so I can see it).  With other attempts, the FilterControl is
>>> not visible at all (zero height).  Forcing an update (by changing focus)
>>> usually clears up the issue and the FilterControl will take its rightful
>>> spot and force the TreeView to be a little less high.
>>> I'm thinking this is somekind of issue with layout and that I'm
>>> approaching this wrong causing the layout problems.  However, I don't quite
>>> understand what I'm possibly doing wrong -- modifying the children of the
>>> Top node of the BorderPane during BorderPane's own
>>> computePref/layoutChildren call should be perfectly fine right?
>>> Any help appreciated!
>>> --John

More information about the openjfx-dev mailing list