Events and Event Dispatch Thread's Queue

Hi,

I have a program that involves a list of tasks and completion status for each task. Normally, each task executes, and then I automatically execute the next task, and all that works wonderfully; however, now I'd like to add a "pause" button that will prevent the next task from automatically executing until the user presses a "resume" button. I have code that implements this, but I've run into a problem because I can't process the pause button's ActionEvent while I'm in my loop that tells my tasks to run (because it's in the Event Dispatch Thread).

I'd rather not use the SwingWorker or start up another thread, because nothing needs to happen in my GUI while the tasks execute (just between their execution), and I don't want to track down all the places in my code that will become unhappy if there's a second thread. What I'd really like to do is, once a task completes and before I execute the next one, tell the JFrame containing the button to handle all its AWTEvents, if there are any (or just handle all its unhandled events, if any).

Question 1: Is there a JComponent or JFrame function that will say "Go handle any events you have on the queue, but don't wait for a new one to show up"? I haven't found one in the API docs, but I might have just missed it.

Alternatively,

Question 2: Is there a way for me to look at the Toolkit.getDefaultToolkit().getSystemEventQueue() and find out whether there are any ActionEvents headed for my object without waiting for one to show up? (If the userdidn't press the pause button, I want to just continue on, not wait until he does). That way I could implement my own function to handle any events that I have on the queue. But in the documentation for EventQueue: getNextEvent waits until it gets an event, getCurrentEvent looks like it wants me to be in the event handler for an event, and I didn't see a way to check whether the queue is empty.

Thanks,

TRL

[2014 byte] By [Thomas_R_Lanea] at [2007-10-2 6:18:28]
# 1

Hi, you will want to use another thread, and interrupt it when the pause button is pressed.

You can totally simulate the loop that runs on the event dispatcher thread. You do that by writing a loop on the app thread and using 'EventQueue.invokeAndWait()' during each iteration to run the body of the loop.

The other approaches you have proposed (queue analysis) are more difficult to implement. Also, you will break the AWT/Swing contract that events must be processed in the order they are dispatched.

jvaudrya at 2007-7-16 13:20:22 > top of Java-index,Desktop,Core GUI APIs...
# 2

Thanks for the help, though I ended up finding a solution on my own.^^

I'd rather not use the SwingWorker or start up another thread, because nothing needs to happen in my GUI while the tasks execute (just between their execution), and I don't want to track down all the places in my code that will become unhappy if there's a second thread, so I found a way to make it work without doing that.

I figured out the peekEvent method of EventQueue will tell me if the queue is empty because it will return null in that case (I don't know why I didn't notice that earlier), so I can just dispatch all the events on the queue to take care of the events I want (naturally I wouldn't want to dispatch them out of order). Unfortunately, EventQueue doesn't have a "dispatchNextEvent" or "dispatchAllEvents" method so I had to implement it myself with the following hack:

EventQueue big_Q = Toolkit.getDefaultToolkit().getSystemEventQueue();

while(big_Q.peekEvent() != null)

{

try

{

AWTEvent e=big_Q.getNextEvent();

Object source;

Class eClass = e.getClass();

Class sClass;

Class eIFs[] = eClass.getInterfaces();

boolean foundIF=false;

for(int i=0;i<eIFs.length;i++)

if (eIFs[i] == ActiveEvent.class)

foundIF=true;

if(foundIF)

((ActiveEvent)e).dispatch();

else if (Component.class.isAssignableFrom(sClass=((source=e.getSource()).getClass())))

((Component)source).dispatchEvent(e);

else if (MenuComponent.class.isAssignableFrom(sClass))

((MenuComponent)source).dispatchEvent(e);

}

catch(java.lang.InterruptedException ex)

{

System.out.println("getNextEvent interrupted!");

}

}

You're right! That was a bit of a pain to implement!

Thanks again,

TRL>

Thomas_R_Lanea at 2007-7-16 13:20:22 > top of Java-index,Desktop,Core GUI APIs...
# 3

Looking at your solution, now I realize I misunderstood your problem in the first place. So you are implementing a method to flush all the events that originate from a Component/MenuComponent. Yeah, does not seem like you need SwingWorker for that.

If you don't mind, what is your program and/or how does it work? Just interested to know.

jvaudrya at 2007-7-16 13:20:22 > top of Java-index,Desktop,Core GUI APIs...
# 4
My program is a front-end for another program, but I'm afraid I can't discuss details about their purpose because it's for work.--TRL
Thomas_R_Lanea at 2007-7-16 13:20:22 > top of Java-index,Desktop,Core GUI APIs...
# 5

There is a problem with my solution, however: I found a sun.awt.PeerEvent event from a java.lang.Object object and didn't know what to do with it, so Swing shut down. Too bad there's no documentation (that I can find) on the sun.awt package. Anybody know how to flush the Swing event buffer automatically or how to make something go handle a sun.awt.PeerEvent?

Thomas_R_Lanea at 2007-7-16 13:20:23 > top of Java-index,Desktop,Core GUI APIs...
# 6

So far, I haven't managed to break this one (I probably ought to break or throw an exception instead of the System.out.println, but I'm debugging):

public void flushEventBuf()

{

EventQueue big_Q = Toolkit.getDefaultToolkit().getSystemEventQueue();

while(big_Q.peekEvent() != null)

{

try

{

AWTEvent e=big_Q.getNextEvent();

Object source = e.getSource();

Class sClass = e.getSource().getClass();

Class eClass = e.getClass();

/* Didn't work for whatever reason */

//Class eIFs[] = eClass.getInterfaces();

//boolean foundIF=false;

//for(int i=0;i<eIFs.length;i++)

// if (eIFs[i] == ActiveEvent.class)

//foundIF=true;

//if(foundIF)

// ((ActiveEvent)e).dispatch();

/**/ if (ActiveEvent.class.isAssignableFrom(eClass))

((ActiveEvent)e).dispatch();

else if (Component.class.isAssignableFrom(sClass))

((Component)source).dispatchEvent(e);

else if (MenuComponent.class.isAssignableFrom(sClass))

((MenuComponent)source).dispatchEvent(e);

else

{

Class eIFs[] = eClass.getInterfaces();

System.out.println("While flushing the event buffer, I found a "+eClass.getName()+" event");

System.out.println("from a "+sClass.getName()+" object and I didn't know what to do with it.");

System.out.println(eClass.getName()+" has superclass "+eClass.getSuperclass().getName());

System.out.println("and implements interfaces:");

for(int i=0;i<eIFs.length;i++)

System.out.println(""+eIFs[i].getName());

}

}

catch(java.lang.InterruptedException ex)

{

System.out.println("getNextEvent interrupted!");

}

}

}

>

Thomas_R_Lanea at 2007-7-16 13:20:23 > top of Java-index,Desktop,Core GUI APIs...