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