Promote addEventHandler/removeEventHandler to EventTarget interface

John Hendrikx john.hendrikx at gmail.com
Tue Mar 7 12:44:04 UTC 2023


Hi Michael,


Did you file a JIRA issue for this one?

I've recently also been doing some rewriting to use the Event system 
more.  I'm removing custom Scene walking code (and looking at 
Node.getProperties) to do "event handling", and I've now discovered that 
it could be done quite a bit nicer by using the provided event mechanism.

I've encountered a few things that annoy me about the event system:

1) I'm making use of Presentation classes (Models) that only associate 
with things in javafx.base (Event, EventTarget, Properties). These 
presentations need to register event handlers at some point, but this 
can only be done on Nodes; having this logic close to the Presentation 
code makes sense, but it would make them dependent on javafx.graphics; 
if I could do this via EventTarget, the dependency would not be needed.

2) When you fire an event (via Node.fireEvent for example), there is no 
feedback you can obtain whether the event was consumed or not as the 
final event is not returned to check `isConsumed` on (internal calls do 
have this information, but it is not exposed at the last step).

3) Related to 2), I think EventTarget could also have a method to 
dispatch events (so you can dispatch an event easily to any target, not 
just via the convenience method Node#fireEvent).  See this ticket: 
https://bugs.openjdk.org/browse/JDK-8303209

Perhaps we can work together on this, or if you're not currently working 
on it I could take a stab at solving all of these issues.

--John
On 07/03/2023 10:24, John Hendrikx wrote:
> Hi Michael,
>
> Did you file a JIRA issue for this one?
>
> I've recently also been doing some rewriting to use the Event system 
> more.  I'm removing custom Scene walking code (and looking at 
> Node.getProperties) to do "event handling", and I've now discovered 
> that it could be done quite a bit nicer by using the provided event 
> mechanism.
>
> I've encountered a few things that annoy me about the event system:
>
> 1) I'm making use of Presentation classes (Models) that only associate 
> with things in javafx.base (Event, EventTarget, Properties). These 
> presentations need to register event handlers at some point, but this 
> can only be done on Nodes; having this logic close to the Presentation 
> code makes sense, but it would make them dependent on javafx.graphics; 
> if I could do this via EventTarget, the dependency would not be needed.
>
> 2) When you fire an event (via Node.fireEvent for example), there is 
> no feedback you can obtain whether the event was consumed or not as 
> the final event is not returned to check `isConsumed` on (internal 
> calls do have this information, but it is not exposed at the last step).
>
> 3) Related to 2), I think EventTarget could also have a method to 
> dispatch events (so you can dispatch an event easily to any target, 
> not just via the convenience method Node#fireEvent).  See this ticket: 
> https://bugs.openjdk.org/browse/JDK-8303209
>
> Perhaps we can work together on this, or if you're not currently 
> working on it I could take a stab at solving all of these issues.
>
> --John
>
> On 17/03/2022 21:01, Michael Strauß wrote:
>> I'm working on an application that uses the JavaFX event system
>> extensively, and I'm finding it quite hard to use common code for
>> event handler registrations.
>>
>> The problem is that the `EventTarget` interface contains no
>> addEventHandler/removeEventHandler methods, and as a consequence of
>> that, code that uses `EventTarget` ends up requiring lots of brittle
>> instanceof tests to call these methods on all the different
>> implementations of `EventTarget`.
>>
>> There are three buckets of `EventTarget` implementations:
>>
>> 1) Implementations that declare the following methods:
>>      <T extends Event> void addEventHandler(EventType<T>,
>> EventHandler<? super T>);
>>      <T extends Event> void removeEventHandler(EventType<T>,
>> EventHandler<? super T>);
>>      <T extends Event> void addEventFilter(EventType<T>, EventHandler<?
>> super T>);
>>      <T extends Event> void removeEventFilter(EventType<T>,
>> EventHandler<? super T>);
>> --> Node, Scene, Window, Transform, Task, Service
>>
>> 2) Implementations that declare the following methods:
>>      <T extends Event> void addEventHandler(EventType<T>, 
>> EventHandler<T>);
>>      <T extends Event> void removeEventHandler(EventType<T>, 
>> EventHandler<T>);
>> --> MenuItem, TreeItem, TableColumnBase
>>
>> (Note that the EventHandler argument ist parameterized as
>> EventHandler<T>, not EventHandler<? super T> as in the first set of
>> methods.)
>>
>> 3) Implementations that don't declare any methods to add or remove
>> event handlers:
>> --> Dialog, Tab
>>
>>
>> I think the situation can be improved by promoting the bucket 1
>> methods to the `EventTarget` interface, so they can be used
>> consistently across all implementations of `EventTarget`.
>>
>> This works seamlessly for bucket 1 and bucket 3 implementations.
>>
>> With bucket 2, there's the problem that, inconsistently, the
>> EventHandler<T> argument is not a lower-bounded wildcard.
>> Unfortunately, a method with an EventHandler<T> parameter cannot
>> implement an interface method that expects EventHandler<? super T>.
>>
>> However, since the erasure of the method remains the same, changing
>> the method signature would technically be a binary-compatible change.
>>
>> Do you think this is a useful improvement?


More information about the openjfx-dev mailing list