我正在使用Java Swing为应用程序呈现我的GUI。我在JButton
上设置了一个ActionListener来启动一系列测试。理想情况下,我想使用实时测试信息和结果更新状态区域(当前为JTextArea
)。换句话说,当测试运行并完成时,程序将逐行设置文本区域:
Running Tests... Test 1: Check Something... Success Test 2: Check Something else... Success .. //More testing output All tests have completed successfully. Yay.
问题是我的actionPerformed
事件方法仍在运行时无法更新状态文本。当所有测试快速完成时,这一切都很好,花花公子。但是,我的一些测试需要无限期的时间才能完成(想想“数据库连接超时”)。发生这种情况时,用户会遇到状态区域中已有的任何文本,我的应用程序会冻结,直到测试完成或失败。
我每次更新状态时都尝试在repaint
上调用JTextArea
,但似乎只是将其添加到事件队列中(直到我的{{之后才会被触发) 1}}事件完成... doh)。我也尝试过调用actionPerformed
和revalidate
,甚至尝试在运行我测试的updateUI
类上调用wait()
,但到目前为止还没有任何工作。这是我当前代码的结构:
ActionListener
非常感谢任何帮助:)
更新
对于那些对解决方案的一般结构感兴趣的人,这里是:
..
JTextArea statusOutput_textArea;
..
public void actionPerformed(ActionEvent e) {
setStatusText("Running Tests...");
//Run Tests
int currentTest = 1;
//Check something
appendStatusText(" Test " + currentTest++ + ": Checking Something...");
.. //Check Something Here
appendStatusText(" Success");
//Check something else
appendStatusText(" Test " + currentTest++ + ": Checking Something else...");
.. //Check Something Else Here
appendStatusText(" Success");
//Other tests
.. //Run other tests here
appendStatusText("\nAll tests have completed successfully. Yay.");
}//End of actionPerformed method
public void setStatusText (String statusText) {
statusOutput_textArea.setText(statusText);
statusOutput_textArea.repaint();
}//End of setStatusText method
public void appendStatusText (String statusTextToAppend) {
statusOutput_textArea.setText(statusOutput_textArea.getText() + "\n" + statusTextToAppend);
statusOutput_textArea.repaint();
}//End of appendStatusText method
答案 0 :(得分:2)
您正在对“Swing线程”进行检查,您最好在不同的thread中执行这些任务(如果发生了某些事情/更改,则会通知GUI。)
答案 1 :(得分:1)
在自己的线程中运行每个测试,以便它们不会相互阻塞。此外,JTextArea已经有一个线程安全的append
方法,无需使用setText
来模拟append
。
答案 2 :(得分:1)
问题是你不能在一个动作中发生长时间运行的任务。正如您所注意到的,当发生这种情况时,什么都不会更新。
您应该尝试查看SwingWorker或其他一些后台线程。您可以在后台线程中运行测试,并且每次要更新要调用的UI时都会执行:
SwingUtils.invokeLater(new Runnable() {
public void run() {
appendStatusText(....);
}
});