我正在创建一个swing应用程序。 它包括使用一些耗时的代码调用函数。
问题是“耗时的代码”,它是在设置Label文本之前调用的。我希望标签在进入下一行之前设置。 为什么会出现这种情况?
myFunction()
{
myLabel.setText("Started");
//time consuming code which creates object of another class
}
注意:启动整个应用程序时我确实使用了java.awt.EventQueue.invokeLater
答案 0 :(得分:5)
您应该在分离的线程中运行耗时的代码:
myFunction(){
myLabel.setText("Started");
new Thread(new Runnable(){
@Override
public void run() {
//time consuming code which creates object of another class
}
}).start();
}
答案 1 :(得分:1)
你应该了解SwingWorker
,它在线程方面给你最大的灵活性。这是短而瘦的:
所有GUI操作都应该在Event Dispatch Thread
(简称EDT)上。所有耗时的任务都应该在后台线程上。 SwingWorker允许您控制正在运行代码的线程。
首先,要在EDT上运行任何内容,请使用以下代码:
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
jLabel1.setText("Yay I'm on the EDT.");
}
});
但是如果你想要执行一项耗时的任务,那将无法满足您的需求。相反,你需要一个像这样的SwingWorker:
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.
*/
}
}
}
}
然后你需要用这个启动你的SwingWorker:
new Task();
有关详细信息,请查看Oracle的文档:http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html