Use ScenePulseListener to avoid expensive recalculations?
John Hendrikx
hjohn at xs4all.nl
Wed Nov 6 10:31:44 PST 2013
On 5/11/2013 20:10, Jonathan Giles 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'm not sure in which circumstances layoutChildren() will be called or
if I can mark my control as needing layout, since the properties I want
to trigger on are not directly attached to anything that JavaFX will be
monitoring. The ScenePulseListener therefore seems like a good choice
-- the reason I'm asking about is that I cannot find any examples and
the documentation for it is also pretty lean.
I'll experiment with a ScenePulseListener and see how it pans out, it
looks like it would be an elegant solution.
Thanks Jonathan!
>
> 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