Use ScenePulseListener to avoid expensive recalculations?

Yennick Trevels yennick.trevels at gmail.com
Tue Nov 5 23:43:44 PST 2013


Isn't it somewhat counter-intuitive to perform such changes in one of the
computePref*() methods? You're adding children in a method which is
supposed to compute the preferred width/height.

There should be a better way to do this. In Apache Flex for example,
there's a commitProperties() and updateDisplayList() method in which you
can do these things, which are called somewhat similar to a pulse in JavaFx
(except that you have to invalidate them yourself).


On Tue, Nov 5, 2013 at 8:10 PM, Jonathan Giles <jonathan.giles at oracle.com>wrote:

> You're right in that controls don't tend to use ScenePulseListener. This
> may be due to an oversight on our part, or just that our requirements
> differ (I don't honestly know).
>
> You're also right that it is important to batch up property changes and
> do them once per pulse, rather than as they come in. If this is not done
> you do indeed get a severe performance hit (I remember back in the day
> before I optimised many of the controls in this way, the performance
> impact of not doing this was staggering).
>
> The way I do it is simple: in places where I receive events from
> properties / bindings / listeners, where I know that there is
> potentially a lot of changes coming through, I create a boolean (e.g.
> 'refreshView' or somesuch). I then set this boolean to true, and in the
> appropriate place in the code (most commonly layoutChildren(), but
> sometimes in the computePref*() methods), I start the method with code
> like this:
>
> if (refreshView) {
>     doExpensiveOperationThatShouldHappenOnlyOncePerPulse();
>     refreshView = false;
> }
>
> The reason why I sometimes use layoutChildren() and sometimes the
> computePref*() methods comes down to the (new) rule in JavaFX 8.0 that
> you can not change the children list of a node within the
> layoutChildren() method. Because of this, if I need to modify the
> children list, I put the above code in the computePref*() method.
>
> I hope that helps.
>
> -- Jonathan
>
> On 6/11/2013 3:58 a.m., John Hendrikx wrote:
> > Hi List,
> >
> > I'm considering using a ScenePulseListener to avoid expensive
> > recalculations when multiple bindings trigger an action.
> >
> > My problem is this:
> >
> > I like to build Views (Controls) that are dumb and expose properties
> > that can be manipulated by whatever is using the View.  The View
> > listens to its own Properties and adjusts its state accordingly.  Some
> > of these adjustments are related (like width + height) and can be
> > expensive when calculated immediately.  So I would like to mark the
> > View as "invalid" and recalculate its state (if invalid) on the next
> > Pulse.
> >
> > My current use case I'm looking at is a View that wraps (amongst
> > others) a TreeView.  The View exposes an ObservableList and a
> > BooleanProperty that decides whether the first level of the Tree
> > should be displayed as Tabs or as Nodes (which has an impact on what
> > Nodes actually are added to the TreeView, and which are added as
> > Tabs).  User code will thus often set a new list of nodes + change the
> > boolean to show tabs or nodes.  The View currently naively has
> > InvalidationListeners on both of these properties which cause
> > TreeNodes to be created after the first change... then discarded and
> > recreated after the second change by the user code, ie:
> >
> >   view.nodesProperty().setAll(nodes);   // Recreates all
> > Tabs/TreeNodes with the current value of expand top level, as we donot
> > know another change might be incoming...
> >   view.expandTopLevelProperty().set(false);   // Recreates all
> > Tabs/TreeNodes again if expand top level was changed...
> >
> > This specific problem might be done in a better way, but the point
> > remains, how do I avoid expensive calculations when multiple
> > properties get changed one after the other by the user code?  I'm
> > assuming that JavaFX controls already avoid these kinds of things, and
> > I'd like to know whether using a ScenePulseListener is the way to go,
> > or that it can/should be done in a different way -- examining the code
> > for TreeView (and its superclasses), I couldn't find uses of
> > ScenePulseListener...
> >
> > --John
> >
> >
> >
> >
>
>


More information about the openjfx-dev mailing list