我是Swing的新手,目前正在尝试在NetBeans中开发一个简单的GUI应用程序。
我想创建某种GUI日志记录系统,将应用程序正在执行的当前操作写入TextArea。
作为一个简单的例子,我创建了一个只包含2个对象的JFrame表单:“开始”按钮和TextArea。
当按下“开始”按钮时,它会调用某种冗长的方法,该方法需要一些时间(比方说,10秒)才能完成运行,并且在此方法运行时,我想将文本附加到TextArea从这个冗长的方法(当然我希望TextArea立即更新)。
我的问题是我无法找到正确的方法。无论如何我尝试这样做,当我按下“开始”按钮时,应用程序冻结了10秒钟,没有像我想要的那样更新TextArea。只有在方法完成后,我才会看到TextArea的更新。
以下是示例代码:
private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {
try {
for (int i = 0; i < 10; i++) {
textArea.setText(i + "\n");
Thread.sleep(1000);
}
} catch (Exception e) {}
}
在这个例子中,我希望看到的是,一旦我点击按钮,在接下来的10秒内,每隔一秒就会在TextArea上添加一行,如下所示:
1
2
3
4
...
但是我从这段代码得到的真正结果是应用程序冻结了10秒钟,最后TextArea被更新并仅显示数字9。
我尝试过很多不同的方法,主要使用 SwingUtilities.invokeLater 和 SwingWorker 方法,但这些方法都不适用于我。
任何帮助找到正确的方法都会非常感激。
答案 0 :(得分:8)
1。始终保持UI工作在UI线程上,非UI工作在非UI线程上。
2。在Java GUI应用程序中,main()
方法在<{1}}中安排GUI的构建后,不长期存在。 main()方法退出......现在它的 EDT负责处理GUI。
3。始终保留您的EDT主题,这是仅用于GUI工作的 GUI主题。
<强>例如强>
Event Dispatcher Thread
4. 创建一个单独的public static void main(String[] args){
EventQueue.invokeLater(new Runnable(){
public void run(){
myframe.setVisible(true);
}
}
}
主题来处理这个长时间的方法。
5. 您可以简单地使用Non-UI
或使用专门引入Java的Thread
来同步UI和非UI线程。强>
答案 1 :(得分:6)
如同其他答案中所述,您将要使用SwingWorker
- 我建议您阅读它,因为它是一个非常有用的工具。此实现应该为您提供样本中所需的内容:
按钮的操作:
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent arg0) {
new Worker().execute();
}
});
你的摇摆工作者:
public class Worker extends SwingWorker<String, String>{
@Override
protected String doInBackground() throws Exception {
//This is what's called in the .execute method
for(int i = 0; i < 10; i++){
//This sends the results to the .process method
publish(String.valueOf(i));
Thread.sleep(1000);
}
return null;
}
protected void process(List<String> item) {
//This updates the UI
textArea.append(item + "\n");
}
}
答案 2 :(得分:3)
使用javax.swing.Timer
课程。有关详细信息,请参阅How to Use Swing Timers。