I have this ActionListener
that gets called in the EDT. My plot() function is computationally heavy, it can easily take five seconds. It made the GUI hang as expected. I added the SwingUtilities.invokeLater
code and it still hangs. Shouldn't the GUI be responsive now that I am spawning a separate thread for my heave computation?
final ActionListener applyListener = new ActionListener()
{
@CommitingFunction
public void actionPerformed(ActionEvent arg0)
{
/*Don't do plotting in the EDT :)*/
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
plot();
}
});
}
};
Not at all. InvokeLater is not producing a new thread. invokeLater exists to tell Swing explicitly "use the Event Dispatching Thread for this, but not right now". invoke and invokeLater exist to let you do operations that are only safe for the Event Dispatching Thread from other threads- not by doing them on those threads, but by telling the EDT to do them.
Your ActionListener will run very quickly, throwing the Runnable on Swing's event dispatching queue. Then when it gets that far, it will take five seconds to run the plot().
The only workaround is to refactor plot(). Use a SwingWorker (or similar multithreading strategy, but SwingWorker is probably the best for this) to actually move the logic of plot() onto a different thread. That thread cannot safely draw anything because it is not the Swing Event Dispatching Thread, so all of its draw operations need to be performed via invokeLater(). For efficiency reasons, you should try to do all of the drawing operations at once, on one invokeLater(), using results stored from your calculation.