如何从long方法中更新swing GUI?

时间:2012-08-05 15:32:56

标签: java multithreading swing user-interface event-dispatch-thread

我是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 方法,但这些方法都不适用于我。

任何帮助找到正确的方法都会非常感激。

3 个答案:

答案 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