-
Bug
-
Resolution: Fixed
-
P3
-
1.1.1, 1.3.0
-
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.
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.
- duplicates
-
JDK-4061850 No user defined ActionEvent Components possible
- Closed
- relates to
-
JDK-4379922 Component.processKeyEvent is not called by event dispatch thread
- Resolved