I try register eventHandler in my custom class. I don\'t know what interface or methods I have to implement for having addEventHandler method in my custom class. Fo
Events are fired using Event.fireEvent which works in 2 steps:
EventDispatchChain using EventTarget.buildEventDispatchChain.Event to the first EventDispatcher in the resulting EventDispatchChain.This code snippet demonstrates the behaviour:
EventTarget target = new EventTarget() {
@Override
public EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) {
return tail.append(new EventDispatcher() {
@Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
System.out.println("Dispatch 1");
tail.dispatchEvent(event);
return event;
}
}).append(new EventDispatcher() {
@Override
public Event dispatchEvent(Event event, EventDispatchChain tail) {
System.out.println("Dispatch 2");
tail.dispatchEvent(event);
return event;
}
});
}
};
Event.fireEvent(target, new Event(EventType.ROOT));
It prints
Dispatch 1
Dispatch 2
As you can see, the way the EventTarget constructs the EventDispatchChain is totally up to the EventTarget.
This explains why you have to implement addEventHandler ect. yourself.
NodesThis is described in detail in the article JavaFX: Handling Events - 1 Processing Events on the Oracle website.
The important details are:
source objects are used during the event handling.EventHandlers / EventFilters are used during the event dispatching (2.).This explains why the source value is unexpected.
addEventHandlerIt's not that hard to do this, if you leave out the event capturing and bubbling. You just need to store the EventHandlers by type in a Map<EventType, Collection>> and call the EventHandlers for each type in the EventType hierarchy:
public class EventHandlerTarget implements EventTarget {
private final Map<EventType, Collection<EventHandler>> handlers = new HashMap<>();
public final <T extends Event> void addEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler) {
handlers.computeIfAbsent(eventType, (k) -> new ArrayList<>())
.add(eventHandler);
}
public final <T extends Event> void removeEventHandler(EventType<T> eventType, EventHandler<? super T> eventHandler) {
handlers.computeIfPresent(eventType, (k, v) -> {
v.remove(eventHandler);
return v.isEmpty() ? null : v;
});
}
@Override
public final EventDispatchChain buildEventDispatchChain(EventDispatchChain tail) {
return tail.prepend(this::dispatchEvent);
}
private void handleEvent(Event event, Collection<EventHandler> handlers) {
if (handlers != null) {
handlers.forEach(handler -> handler.handle(event));
}
}
private Event dispatchEvent(Event event, EventDispatchChain tail) {
// go through type hierarchy and trigger all handlers
EventType type = event.getEventType();
while (type != Event.ANY) {
handleEvent(event, handlers.get(type));
type = type.getSuperType();
}
handleEvent(event, handlers.get(Event.ANY));
return event;
}
public void fireEvent(Event event) {
Event.fireEvent(this, event);
}
}