views:

64

answers:

6

I've created a Swing component which has several methods.
Now I want all methods of this class be run on Event Dispatch Thread (EDT), while callers are on Worker threads. The only solution currently in my mind is this:
for each method

public void a(params)  

on this class, I should rename it to

private void aOnEDT(params)  

and add another method

 
public void a(params){
    SwingUtilities.invokeAndWait(new Runnable(){
        public void run() {
            aOnEDT(params);
        }
    });
}

But isn't it nasty?

How can I do this?

I hope someone help me out of this.

Thank you

+1  A: 

Whenever you want something to execute on the Event Dispatch Thread, you should use SwingUtilities.invokeLater(Runnable doRun).

Extract from the Javadoc:

Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI.

Gnoupi
+1  A: 

In all of the methods you need to run on the EDT you should wrap the method body in the following code:

SwingUtilities.invokeLater(new Runnable(){public void run(){


    // All code placed in here will be ran asynchronously on the EDT


}});

This will cause all things in the method to be ran on the EDT. Because you are running code on the EDT, you should not be doing anything that will block for a long time. (File IO, long computations, etc) Otherwise your GUI will freeze and become unresponsive.

invokeLater() javadocs

jjnguy
Thank you for your response. Isn't there any solution that works for all methods without changing all of current and upcoming methods?
mohsenof
@mhosenof I could not think of one. This is the best solution I could think of. If you format it like I did, it is only 2 extra lines.
jjnguy
@mohsenof It is not usually the case that someone wants every method to run on the EDT because it could cause your GUI to run slowly if too many things happen on the EDT.
jjnguy
+2  A: 

You could test whether the call is currently being made on the EDT or not, and drop a Runnable into SwingUtilites.invokeLater() if it isnt:

public void myMethod() {
       if (SwingUtilities.isEventDispatchThread()) {
            //... your code
       } else {
           SwingUtilities.invokeLater(
                  new Runnable(){
                     public void run() {
                           myMethod();
                     }
                  });
       {
  }                   

This will keep the method running if it you are on the EDT, without putting it to the end of the event queue.

akf
Hmm, nice way to make sure the method is executed on the EDT.
Gnoupi
This is very good to use when developing your program, but in the long run you should not rely on this and instead realize which calls are already on the EDT and which aren't--this adds a lot of mess and--I hate to mention performance but a significant overhead if it's done a lot (like a few hundred times a second or more).
Bill K
A: 

Use a SwingWorker and update your GUI-Components in the done() method. Do the background work in the donInBackground() method.

keuleJ
From his question, it seems he is already using worker threads.
Gnoupi
A: 

One way we accomplished that is using AspectJ. The boilerplate code is injected during compilation into all methods annotated with @OnEDT. Resulting code is slim and very convenient.

Obliviously we had to create the annotation, pointcut and aspect for that, but that was almost trivial.

Here are few related links if you're interested:

http://www.eclipse.org/aspectj/

http://www.eclipse.org/ajdt/EclipseCon2006/

http://www.cs.wustl.edu/~mdeters/doc/slides/aspectjtutorial.pdf

eugener
A: 

Thank you for all of your responses. Finally we (well, just my friend not me!) created a wrapper class around our component. This wrapper receives all calls, creates a runnable (inside run() we call actual method) and send this runnable to invokeLater().
All of this seems to be not so complicated using reflection library. The starting point is java.lang.reflect.Proxy class which dynamically creates an instance of an interface.

mohsenof