Java Swing:在长事件期间重绘组件

时间:2011-05-19 18:02:31

标签: java events swing actionlistener repaint

我正在使用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)。我也尝试过调用actionPerformedrevalidate,甚至尝试在运行我测试的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 

3 个答案:

答案 0 :(得分:2)

您正在对“Swing线程”进行检查,您最好在不同的thread中执行这些任务(如果发生了某些事情/更改,则会通知GUI。)

答案 1 :(得分:1)

在自己的线程中运行每个测试,以便它们不会相互阻塞。此外,JTextArea已经有一个线程安全的append方法,无需使用setText来模拟append

答案 2 :(得分:1)

问题是你不能在一个动作中发生长时间运行的任务。正如您所注意到的,当发生这种情况时,什么都不会更新。

您应该尝试查看SwingWorker或其他一些后台线程。您可以在后台线程中运行测试,并且每次要更新要调用的UI时都会执行:

SwingUtils.invokeLater(new Runnable() {
     public void run() {
        appendStatusText(....);
    }
});