通常,SwingWorker用于在Swing中执行长时间运行的任务。
在事件分派线程(EDT)上运行长时间运行的任务可能导致GUI锁定,所以做的事情之一是使用SwingUtilities.invokeLater和invokeAndWait,它保持GUI响应,在运行之前优先考虑其他AWT事件期望的任务(以Runnable的形式)。
但是,SwingUtilities的问题是它不允许从执行的Runnable返回数据到原始方法。这是SwingWorker旨在解决的。
Java教程在SwingWorker有一节。
下面是一个例子,其中使用SwingWorker在单独的线程上执行一个耗时的任务,并在稍后显示一个消息框与答案。
首先,将扩展SwingWorker的类:
class AnswerWorker extends SwingWorker
{
protected Integer doInBackground() throws Exception
{
// Do a time-consuming task.
Thread.sleep(1000);
return 42;
}
protected void done()
{
try
{
JOptionPane.showMessageDialog(f, get());
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
doInBackground和get方法的返回类型被指定为SwingWorker的第一个类型,第二个类型是用于返回发布和处理方法的类型,在本示例中未使用它们。
然后,为了调用SwingWorker,调用execute方法。在这个例子中,我们将一个ActionListener挂钩到一个JButton来执行AnswerWorker:
JButton b = new JButton("Answer!");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
new AnswerWorker().execute();
}
});
上面的按钮可以添加到一个JFrame,并点击获得一个消息框一秒钟后。以下内容可用于初始化Swing应用程序的GUI:
private void makeGUI()
{
final JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new FlowLayout());
// include: "class AnswerWorker" code here.
// include: "JButton" b code here.
f.getContentPane().add(b);
f.getContentPane().add(new JButton("Nothing"));
f.pack();
f.setVisible(true);
}
一旦应用程序运行,将有两个按钮。一个标签为“回答!和另一个“没有”。当一个人点击“回答!”按钮,首先不会发生,但是点击“没有”按钮将工作,并演示GUI是响应。
然后,一秒钟后,AnswerWorker的结果将显示在消息框中。