Implementation not following documentation regarding when event handler gets called
John Hendrikx
john.hendrikx at gmail.com
Sun May 28 10:02:17 UTC 2023
When looking at the code for Scene#setOnKeyPressed, I noticed that it
calls Scene#setEventHandler. This is documented as:
/**
* Sets the handler to use for this event type. There can only be
one such
* handler specified at a time. This handler is guaranteed to be called
* first. This is used for registering the user-defined onFoo event
* handlers.
*
* @param <T> the specific event class of the handler
* @param eventType the event type to associate with the given
eventHandler
* @param eventHandler the handler to register, or null to unregister
* @throws NullPointerException if the event type is null
*/
protected final <T extends Event> void setEventHandler(
final EventType<T> eventType,
final EventHandler<? super T> eventHandler) {
Note that it specifically says "This handler is guaranteed to be called
first."
This function eventualy calls CompositeEventHandler#setEventHandler.
This class tracks a chain of handlers, and reserves a special spot for a
single special "eventHandler". Yet, in its dispatchBubblingEvent
method, it clearly calls the "special" handler LAST... see below:
public void dispatchBubblingEvent(final Event event) {
final T specificEvent = (T) event;
EventProcessorRecord<T> record = firstRecord;
while (record != null) {
if (record.isDisconnected()) {
remove(record);
} else {
record.handleBubblingEvent(specificEvent);
}
record = record.nextRecord;
}
if (eventHandler != null) {
eventHandler.handle(specificEvent);
}
}
I've confirmed this with this small program (order of calls doesn't make
a difference):
public static class App extends Application {
@Override
public void start(Stage primaryStage) {
Button button1 = new Button("111");
HBox hBox = new HBox();
hBox.getChildren().addAll(button1);
Scene scene = new Scene(hBox, 300, 300);
scene.addEventHandler(KeyEvent.KEY_PRESSED, e -> {
System.out.println("KeyPressedHandler " + e);
});
scene.setOnKeyPressed(e -> {
System.out.println("Main " + e);
e.consume();
});
primaryStage.setScene(scene);
primaryStage.show();
}
Which outputs the events not in the order documented:
KeyPressedHandler KeyEvent [source = javafx.scene.Scene at 36dbf594, target
= Button at 5dd3d27e[styleClass=button]'111', eventType = KEY_PRESSED,
consumed = false, character = , text = f, code = F]
Main KeyEvent [source = javafx.scene.Scene at 36dbf594, target =
Button at 5dd3d27e[styleClass=button]'111', eventType = KEY_PRESSED,
consumed = false, character = , text = f, code = F]
--John
More information about the openjfx-dev
mailing list