Promote addEventHandler/removeEventHandler to EventTarget interface
John Hendrikx
john.hendrikx at gmail.com
Fri Mar 18 21:52:55 UTC 2022
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.
I think it would make good sense that they also have the
EventHandler/Filters methods for consistency. If they're targets for
Events, then you should be able to add handlers or filters for them.
> 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.
They also forward directly to the internal EventHandlerManager which
does accept EventHandler<? super T>. This seems like an oversight when
those implementations were added to MenuItem, TreeItem and TableColumnBase.
> Do you think this is a useful improvement?
I think that all the implementations should definitely be consistent;
Dialog and Tab probably should have the means to add EventHandlers and
EventFilters; and MenuItem, TreeItem, TableColumnBase could do with the
EventFilter variants.
If they're going to be consistent, might as well add these methods to
the EventTarget interface to enforce this for any future EventTarget
implementations.
EventTarget is already public API, and so there might be 3rd party
implementations. This means that the methods added to the EventTarget
interface must be default methods. It would be super if these default
implementations would just work out of the box, but that would require
exposing the internal class EventHandlerManager (and adding a
`getEventHandlerManager` to the `EventTarget` interface). If that's not
realistic, then initially the default implementations would have to
throw UnsupportedOperationException.
--John
More information about the openjfx-dev
mailing list