问题
I am creating a swing application. It consists of calling a function with some time consuming code.
The problem is the "time consuming code" , it is called before the Label's text is set. I want the label to be set before it goes onto the next line. Why does this occour ?
myFunction()
{
myLabel.setText("Started");
//time consuming code which creates object of another class
}
Note: I did use java.awt.EventQueue.invokeLater when starting the entire application
回答1:
It would behoove you to learn about SwingWorker
which gives you ultimate flexibility when it comes to threading. Here's the short and skinny:
All GUI actions should be on the Event Dispatch Thread
(EDT for short). All time-consuming tasks should be on background threads. SwingWorker allows you to control which thread you're running code on.
First, to run anything on the EDT, you use this code:
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
jLabel1.setText("Yay I'm on the EDT.");
}
});
But if you want to run a time-consuming task, that won't do what you need. Instead, you'll need a SwingWorker like this:
class Task extends SwingWorker<Void, Void> {
public Task() {
/*
* Code placed here will be executed on the EDT.
*/
jLabel1.setText("Yay I'm on the EDT.");
execute();
}
@Override
protected Void doInBackground() throws Exception {
/*
* Code run here will be executed on a background, "worker" thread that will not interrupt your EDT
* events. Run your time consuming tasks here.
*
* NOTE: DO NOT run ANY Swing (GUI) code here! Swing is not thread-safe! It causes problems, believe me.
*/
return null;
}
@Override
protected void done() {
/*
* All code run in this method is done on the EDT, so keep your code here "short and sweet," i.e., not
* time-consuming.
*/
if (!isCancelled()) {
boolean error = false;
try {
get(); /* All errors will be thrown by this method, so you definitely need it. If you use the Swing
* worker to return a value, it's returned here.
* (I never return values from SwingWorkers, so I just use it for error checking).
*/
} catch (ExecutionException | InterruptedException e) {
// Handle your error...
error = true;
}
if (!error) {
/*
* Place your "success" code here, whatever it is.
*/
}
}
}
}
Then you need to launch your SwingWorker with this:
new Task();
For more info, check out Oracle's documentation: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
回答2:
You should run your time consuming code in a separated thread :
myFunction(){
myLabel.setText("Started");
new Thread(new Runnable(){
@Override
public void run() {
//time consuming code which creates object of another class
}
}).start();
}
来源:https://stackoverflow.com/questions/18783513/performing-two-actions-in-order