Reputation: 7706
My understanding is that if I start up another thread to perform some actions, I would need to SwingUtilities.invokeAndWait
or SwingUtilities.invokeLater
to update the GUI while I'm in said thread. Please correct me if I'm wrong.
What I'm trying to accomplish is relatively straightforward: when the user clicks submit, I want to (before performing any actions) disable the submit button, perform the action, and at the end of the action re-enable the button. My method to perform the action updates the GUI directly (displays results) when it gets the results back.
This action basically queries a server and gets some results back.
What I have so far is:
boolean isRunning = false;
synchronized handleButtonClick() {
if ( isRunning == false ) {
button.setEnabled( false );
isRunning = true;
doAction();
}
}
doAction() {
new Thread() {
try {
performAction(); // Concern A
} catch ( ... ) {
displayStackTrace( ... ); // Concern B
} finally {
SwingUtilities.invokeLater ( /* simple Runnable to enable button */ );
isRunning = false;
}
}
}
For both of my concerns above, do I would have to use SwingUtilities.invokeAndWait
since they both will update the GUI? All GUI updates revolve around updating JTextPane
. Do I need to in my thread check if I'm on EDT and if so I can call my code (regardless of whether it updates the GUI or not) and NOT use SwingUtilities.invokeAndWait
?
EDIT: Here is what I am doing now:
handleButtonClick() {
if ( isRunning == true )
return;
disable button;
SwingWorker task = new MyTask();
task.execute();
}
...inside MyTask
doInBackground() {
return performAction();
}
done() {
result = get();
enable button;
isRunning = false;
interpret result (do most of the GUI updates here);
}
While performAction()
does some GUI updates, I have wrapped those in:
if ( SwingUtil.isEDT() )
doGUIupdate()
else
SwingUtil.invokeLater( new Runnable() {
run() {
doGUIupdate();
}
} );
Hopefully this is a step in the right direction, please comment if you believe there are better ways to handle my situation.
Upvotes: 13
Views: 7876
Reputation: 4965
I keep the simple Thread
inside EventQueue.invokeLater(...)
and that worked smoothly...
java.awt.EventQueue.invokeLater(new Runnable() {
public void run(){
new Thread(new Runnable(){
public void run(){
try{
EdgeProgress progress = EdgeProgress.getEdgeProgress();
System.out.println("now in traceProgressMonitor...");
while(true){
// here the swing update
if(monitor.getState() == ProgressMonitor.STATE_BUSY){
System.out.println(monitor.getPercentDone()/2);
progress.setProgress(monitor.getPercentDone()/2);
}else{
break;
}
Thread.sleep(5);
}
}catch(InterruptedException ie){}
}
}).start();
}
});
Upvotes: 0
Reputation: 625347
In my opinion you should almost never use invokeAndWait()
. If something is going to take awhile that will lock your UI.
Use a SwingWorker
for this kind of thing. Take a look at Improve Application Performance With SwingWorker in Java SE 6.
Upvotes: 18
Reputation: 134255
You should consider using SwingWorker
since it will not block the UI thread, whereas both SwingUtilities
methods will execute on the EDT thread, thus blocking the UI.
Upvotes: 5