Didn't look too deep, but seems like a bug or incorrect doc. I don't see such specifications in other "setOnX" methods.
On Sun, May 28, 2023 at 1:02 PM John Hendrikx <john.hendr...@gmail.com> wrote: > 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@36dbf594, target > = Button@5dd3d27e[styleClass=button]'111', eventType = KEY_PRESSED, > consumed = false, character = , text = f, code = F] > Main KeyEvent [source = javafx.scene.Scene@36dbf594, target = > Button@5dd3d27e[styleClass=button]'111', eventType = KEY_PRESSED, > consumed = false, character = , text = f, code = F] > > --John > >