Event Dispatching Problem
I use "my own" event processing, mainly to deal with modal dialogs.
publicstaticvoid dispatchEvent(AWTEvent event)
{
assert SwingUtilities.isEventDispatchThread() ;
if (eventinstanceof ActiveEvent){
((ActiveEvent)event).dispatch() ;
}
elseif (sourceinstanceof Component){
((Component)source).dispatchEvent(event) ;
}
elseif (sourceinstanceof MenuComponent){
((MenuComponent)source).dispatchEvent(event) ;
}
else{
thrownew RuntimeException("Unable to dispatch: " + event) ;
}
}
However, sometimes the dipatching blocks on a SequencedEvent. The GUI is frozen and gets only unblocked when interrupting the event dispatching thread. The EDT stack trace tells me in this case:
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
java.awt.EventQueue.getNextEvent(Unknown Source)
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.SequencedEvent.dispatch(Unknown Source)
my.SwingEvent.dispatchEvent(SwingEvent.java:55)
So it appears that the SequencedEvent is not the first in its list; however there are neither any events pending. How can this happen?
Any ideas are highly appreciated! Thx & rgds
[2304 byte] By [
Crauda] at [2007-11-27 8:27:43]

# 4
Since the problem still persists, here some code to reproduce it.
import java.awt.* ;
import java.awt.event.* ;
import java.util.* ;
import javax.swing.* ;
import javax.swing.event.* ;
class Main
{
static boolean debug ;
static void log(String message)
{
if (debug)
System.err.println(message) ;
}
// we force all execution to the event dispatching thread
public static void main(String[] args)
{
debug = args.length == 1 && args[0].equals("debug") ;
Runnable runnable = new Runnable() {
public void run() { execute() ; }
} ;
SwingUtilities.invokeLater(runnable) ;
}
// local event dispatching controlled by the user
static class SwingEvent
{
static AWTEvent getNextEvent()
{
try {
return Toolkit.getDefaultToolkit().getSystemEventQueue().getNextEvent() ;
}
catch (InterruptedException exception) {
throw new RuntimeException("Interrupted event dispatching") ;
}
}
static void dispatchEvent(AWTEvent event)
{
if (event instanceof ActiveEvent) {
((ActiveEvent)event).dispatch() ;
}
else {
Object source = event.getSource() ;
if (source instanceof Component) {
((Component)source).dispatchEvent(event) ;
}
else if (source instanceof MenuComponent) {
((MenuComponent)source).dispatchEvent(event) ;
}
else {
throw new RuntimeException("Unable to dispatch: " + event) ;
}
}
}
static void processEvent()
{
assert SwingUtilities.isEventDispatchThread() ;
dispatchEvent(getNextEvent()) ;
}
}
// the start method executes the required operation in a dedicated
// thread. however, the method does not return until the operation
// is completed. all new events are processed while the operation
// is in progress. -- this enables some sequential flow of control.
static class Worker
{
boolean finished = false ;
protected void invoke() {} // to be overloaded by the client
private void setFinished()
{
Runnable runnable = new Runnable() {
@Override public void run()
{
finished = true ;
log("set finished") ;
}} ;
SwingUtilities.invokeLater(runnable) ;
}
public void start()
{
assert SwingUtilities.isEventDispatchThread() ;
log("start...") ;
Runnable runnable = new Runnable() {
@Override public void run() {
log("about to invoke...") ;
invoke() ;
log("...invoke finished.") ;
setFinished() ;
}} ;
new Thread(runnable).start() ;
while (!finished) {
log("about to process event...") ;
SwingEvent.processEvent() ;
log("...event processed.") ;
}
log("...finished.") ;
}
}
// the watchdog for the event dispatching thread
static class SwingWatchdog
{
boolean stillWaiting = false ;
Thread swingThread = Thread.currentThread() ;
static void dumpStack(Thread thread)
{
Map<Thread,StackTraceElement[]> map = Thread.getAllStackTraces() ;
StackTraceElement[] array = map.get(thread) ;
for (StackTraceElement element : array) {
System.err.println(element) ;
}
}
void poll()
{
while (true) {
stillWaiting = true ;
Runnable runnable = new Runnable() {
@Override public void run() { stillWaiting = false ; }} ;
SwingUtilities.invokeLater(runnable) ;
try { Thread.sleep(5000) ; }
catch (InterruptedException exception) {}
if (stillWaiting) {
System.err.println("Swing did not respond!") ;
dumpStack(swingThread) ;
swingThread.interrupt() ;
}
}
}
public static SwingWatchdog init()
{
assert SwingUtilities.isEventDispatchThread() ;
final SwingWatchdog watchdog = new SwingWatchdog() ;
Runnable runnable = new Runnable() {
@Override public void run() { watchdog.poll() ; }} ;
new Thread(runnable).start() ;
return watchdog ;
}
}
static void execute()
{
final JFrame frame = new JFrame("Problem with SequencedEvent?") ;
// create a list; the list is only used to catch keyboard events...
Integer[] items = new Integer[100] ;
for (int i=0 ; i<100 ; ++i) {
items[i] = i ;
}
JList jList = new JList(items) ;
// ...which start up worker threads
jList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) { processEvent(frame) ; }}) ;
frame.add(jList) ;
frame.setBounds(100, 100, 100, 400) ;
frame.setVisible(true) ;
SwingWatchdog.init() ;
while (true)
SwingEvent.processEvent() ;
}
static void processEvent(JFrame frame)
{
log("process list event...") ;
JDialog dialog = new JDialog(frame, "Please...", false) ;
dialog.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE) ;
dialog.add(new JLabel("...wait")) ;
dialog.setLocation(100,200) ;
dialog.pack();
dialog.setVisible(true) ;
new Worker().start() ;
dialog.setVisible(false) ;
log("...list event processed.") ;
}
}
After starting the program (from a terminal), a window appears with a list of numbers. Just click into the list and press and hold thereafter the "down" key on your keyboard. Instead of browsing thru the list, the program gets stuck and nothing happens until the watchdog interrupts the Swing thread. On the terminal should appear a stack trace like:
Swing did not respond!
java.lang.Object.wait(Native Method)
java.lang.Object.wait(Object.java:485)
java.awt.EventQueue.getNextEvent(Unknown Source)
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.SequencedEvent.dispatch(Unknown Source)
Main$SwingEvent.dispatchEvent(Main.java:43)
Main$SwingEvent.processEvent(Main.java:62)
Main$Worker.start(Main.java:101)
Main.processEvent(Main.java:180)
Main$2.valueChanged(Main.java:162)
javax.swing.JList.fireSelectionValueChanged(Unknown Source)
javax.swing.JList$ListSelectionHandler.valueChanged(Unknown Source)
javax.swing.DefaultListSelectionModel.fireValueChanged(Unknown Source)
javax.swing.DefaultListSelectionModel.fireValueChanged(Unknown Source)
javax.swing.DefaultListSelectionModel.fireValueChanged(Unknown Source)
javax.swing.DefaultListSelectionModel.changeSelection(Unknown Source)
javax.swing.DefaultListSelectionModel.changeSelection(Unknown Source)
javax.swing.DefaultListSelectionModel.setSelectionInterval(Unknown Source)
javax.swing.JList.setSelectedIndex(Unknown Source)
javax.swing.plaf.basic.BasicListUI$Actions.changeSelection(Unknown Source)
javax.swing.plaf.basic.BasicListUI$Actions.actionPerformed(Unknown Source)
javax.swing.SwingUtilities.notifyAction(Unknown Source)
javax.swing.JComponent.processKeyBinding(Unknown Source)
javax.swing.JComponent.processKeyBindings(Unknown Source)
javax.swing.JComponent.processKeyEvent(Unknown Source)
java.awt.Component.processEvent(Unknown Source)
java.awt.Container.processEvent(Unknown Source)
java.awt.Component.dispatchEventImpl(Unknown Source)
java.awt.Container.dispatchEventImpl(Unknown Source)
java.awt.Component.dispatchEvent(Unknown Source)
java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
java.awt.DefaultKeyboardFocusManager.pumpApprovedKeyEvents(Unknown Source)
java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
java.awt.Component.dispatchEventImpl(Unknown Source)
java.awt.Container.dispatchEventImpl(Unknown Source)
java.awt.Window.dispatchEventImpl(Unknown Source)
java.awt.Component.dispatchEvent(Unknown Source)
java.awt.EventQueue.dispatchEvent(Unknown Source)
java.awt.SequencedEvent.dispatch(Unknown Source)
Main$SwingEvent.dispatchEvent(Main.java:43)
Main$SwingEvent.processEvent(Main.java:62)
Main.execute(Main.java:168)
Main$1.run(Main.java:22)
java.awt.event.InvocationEvent.dispatch(Unknown Source)
java.awt.EventQueue.dispatchEvent(Unknown Source)
java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.pumpEvents(Unknown Source)
java.awt.EventDispatchThread.run(Unknown Source)
I would appreciate if someone could confirm the problem (I use Swing 6 on XP). Maybe there is a problem if a SequencedEvent is dispatched by another SequencedEvent?
I hope I could described the problem with the code above; and I hope I made no stupid errors (in my real application, Swing is completely frozen, while Swing is not in the example above).
Any ideas to solve the problem are highly appreciated.
thx & rgds, Craud
Crauda at 2007-7-12 20:17:27 >
