[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openjdk-openjfx-dev
Subject:    Re: Implementation not following documentation regarding when event handler gets called
From:       Nir Lisker <nlisker () gmail ! com>
Date:       2023-05-29 20:34:35
Message-ID: CA+0ynh_CA3BvAazrPzwbOukQNcTny=dWcA-9TkwEsrEqVLmjyA () mail ! gmail ! com
[Download RAW message or body]

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.hendrikx@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
>
>

[Attachment #3 (text/html)]

<div dir="ltr">Didn&#39;t look too deep, but seems like a bug or incorrect doc. I \
don&#39;t see such specifications in other &quot;setOnX&quot; methods.</div><br><div \
class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, May 28, 2023 at \
1:02 PM John Hendrikx &lt;<a \
href="mailto:john.hendrikx@gmail.com">john.hendrikx@gmail.com</a>&gt; \
wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px \
0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">When looking at the \
code for Scene#setOnKeyPressed, I noticed that it <br> calls Scene#setEventHandler.   \
This is documented as:<br> <br>
         /**<br>
           * Sets the handler to use for this event type. There can only be <br>
one such<br>
           * handler specified at a time. This handler is guaranteed to be called<br>
           * first. This is used for registering the user-defined onFoo event<br>
           * handlers.<br>
           *<br>
           * @param &lt;T&gt; the specific event class of the handler<br>
           * @param eventType the event type to associate with the given <br>
eventHandler<br>
           * @param eventHandler the handler to register, or null to unregister<br>
           * @throws NullPointerException if the event type is null<br>
           */<br>
         protected final &lt;T extends Event&gt; void setEventHandler(<br>
                         final EventType&lt;T&gt; eventType,<br>
                         final EventHandler&lt;? super T&gt; eventHandler) {<br>
<br>
Note that it specifically says &quot;This handler is guaranteed to be called <br>
first.&quot;<br>
<br>
This function eventualy calls CompositeEventHandler#setEventHandler.   <br>
This class tracks a chain of handlers, and reserves a special spot for a <br>
single special &quot;eventHandler&quot;.   Yet, in its dispatchBubblingEvent <br>
method, it clearly calls the &quot;special&quot; handler LAST... see below:<br>
<br>
         public void dispatchBubblingEvent(final Event event) {<br>
                 final T specificEvent = (T) event;<br>
<br>
                 EventProcessorRecord&lt;T&gt; record = firstRecord;<br>
                 while (record != null) {<br>
                         if (record.isDisconnected()) {<br>
                                 remove(record);<br>
                         } else {<br>
                                 record.handleBubblingEvent(specificEvent);<br>
                         }<br>
                         record = record.nextRecord;<br>
                 }<br>
<br>
                 if (eventHandler != null) {<br>
                         eventHandler.handle(specificEvent);<br>
                 }<br>
         }<br>
<br>
I&#39;ve confirmed this with this small program (order of calls doesn&#39;t make <br>
a difference):<br>
<br>
         public static class App extends Application {<br>
             @Override<br>
             public void start(Stage primaryStage) {<br>
                 Button button1 = new Button(&quot;111&quot;);<br>
<br>
                 HBox hBox = new HBox();<br>
                 hBox.getChildren().addAll(button1);<br>
                 Scene scene = new Scene(hBox, 300, 300);<br>
<br>
                 scene.addEventHandler(KeyEvent.KEY_PRESSED, e -&gt; {<br>
                     System.out.println(&quot;KeyPressedHandler &quot; + e);<br>
                 });<br>
                 scene.setOnKeyPressed(e -&gt; {<br>
                     System.out.println(&quot;Main &quot; + e);<br>
                     e.consume();<br>
                 });<br>
<br>
                 primaryStage.setScene(scene);<br>
                 primaryStage.show();<br>
             }<br>
<br>
Which outputs the events not in the order documented:<br>
<br>
KeyPressedHandler KeyEvent [source = javafx.scene.Scene@36dbf594, target <br>
= Button@5dd3d27e[styleClass=button]&#39;111&#39;, eventType = KEY_PRESSED, <br>
consumed = false, character =   , text = f, code = F]<br>
Main KeyEvent [source = javafx.scene.Scene@36dbf594, target = <br>
Button@5dd3d27e[styleClass=button]&#39;111&#39;, eventType = KEY_PRESSED, <br>
consumed = false, character =   , text = f, code = F]<br>
<br>
--John<br>
<br>
</blockquote></div>



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic