Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4292099

AWT Event delivery to processEvent

XMLWordPrintable

    • beta2
    • x86, sparc
    • solaris_7, windows_nt
    • Verified

      Certain AWT events cannot be delivered to the processEvent method of
      components that are not in the java.awt package. While this is largely
      the same problem noted in 4061850, this report is more comprehensive and
      should supercede that older one.

      These event classes in question are

      ActionEvent
      AdjustmentEvent
      ItemEvent
      TextEvent

      A small app exists at /home/dherron/work/4061850 that illustrates the
      problem and certain workaround possibilities.

      The effect is to make it harder to implement lightweight components, and
      it leads to possible application performance problems.

      By "cannot be delivered", what I mean is

       0- You have a component class, having it enableEvents for the appropriate
         mask, set up a processEvent method that recognizes the xxxEvent class
         and forwards the event to processXXXEvent, as is usual. I used the
         java.awt.Button source code as a pattern to follow.
       1- You create a new xxxEvent object.
       2- Post this event into the system event queue.
       3- You expect this event to be delivered to processEvent and processXXXEvent,
         that will then forward the event to any xxxEventListener objects.

      According to the javadoc:

        protected final void enableEvents(long eventsToEnable)

          Enables the events defined by the specified event mask
          parameter to be delivered to this component.

          Event types are automatically enabled when a listener for
          that event type is added to the component.

          This method only needs to be invoked by subclasses of Component
          which desire to have the specified event types delivered to processEvent
          regardless of whether or not a listener is registered.

      Hence you would expect the following to deliver ActionEvents to the
      components processEvent method:

        class btn extends Component {
      public btn() {
      ...
      enableEvents(AWTEvent.ACTION_EVENT_MASK);
                      addMouseListener( new MouseAdapter() {
                      public void mouseClicked(MouseEvent e) {
                          ActionEvent ae = new ActionEvent(e.getSource(),
      ActionEvent.ACTION_PERFORMED,
      getActionCommand());
                          Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ae);
                      }
                      });
      }

              public synchronized void addActionListener(ActionListener l) {
      if (l == null) {
      return;
      }
      enableEvents(AWTEvent.ACTION_EVENT_MASK);
      actionListener = AWTEventMulticaster.add(actionListener, l);
      }
        }

      This prevents a goal in event handling stated at
      http://java.sun.com/docs/books/tutorial/uiswing/overview/event.html

      Important: The code in event handlers should execute very quickly!
      Otherwise, your program's perceived performance will be poor.
      If you need to perform some lengthy operation as the result
      of an event, do it by starting up another thread (or somehow
      sending a request to another thread)

      That is, the best workaround for this problem is to implement the mouseListener
      as follows:


        class btn extends Component {
      public btn() {
      ...
      enableEvents(AWTEvent.ACTION_EVENT_MASK);
                      addMouseListener( new MouseAdapter() {
                      public void mouseClicked(MouseEvent e) {
                          ActionEvent ae = new ActionEvent(e.getSource(),
      ActionEvent.ACTION_PERFORMED,
      getActionCommand());
                          processEvent(ae);
                      }
                      });
      }
      ...
        }

      The effect of calling processEvent directly is that you extend the
      amount of time that the MouseEvent delivery takes. It is not known
      the amount of time delivery of the ActionEvent will take, and chaining
      together event deliveries in this way can lead to problems (say, if one
      or more of the listeners for the ActionEvent then chain off other event
      dispatches in the same way rather than using the event queue).

      It is better that the design goal (event handlers execute very quickly)
      be adhered to and supported by the toolkit.



      The life cycle of an event is as follows:

        generate event

        post it to the event queue

        AWT event processing loop takes it off the queue and dispatches
        it to the component.

        it arrives at <component>.dispatchEvent and propogates to
        processEvent

        processEvent looks at the event class and propogates it to
        the appropriate processXXEvent

        processXXEvent checks the listeners and, if any, calls the approprite
        listener delivery method

      This problem breaks that life cycle at the dispatchEvent location.

            mbronsonsunw Mike Bronson (Inactive)
            dherronsunw David Herron (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: