如何在Java中使用SwingWorker?

时间:2009-04-23 15:28:33

标签: java swingworker

  

与我之前的问题相关:Call repaint from another class in Java?

我是Java的新手,我已经看过一些关于SwingWorker的教程。然而,我不确定如何使用我在上一个问题中给出的示例代码来实现它。

任何人都可以解释如何使用SwingWorker关于我的代码片段和/或指向一个体面的教程吗?我看了,但我不确定我还明白。

2 个答案:

答案 0 :(得分:105)

通常,SwingWorker用于在Swing中执行长时间运行的任务。

在事件调度线程(EDT)上运行长时间运行的任务会导致GUI锁定,因此所做的一件事就是使用SwingUtilities.invokeLaterinvokeAndWait来保持GUI响应,在运行所需任务之前优先处理其他AWT事件(以Runnable的形式)。

然而,SwingUtilities的问题在于它不允许将执行的Runnable中的数据返回到原始方法。这就是SwingWorker旨在解决的问题。

Java Tutorial有一节关于SwingWorker

以下是一个示例,其中SwingWorker用于在单独的线程上执行耗时的任务,并在一秒钟后显示一个消息框并给出答案。

首先,将进行一个扩展SwingWorker的课程:

class AnswerWorker extends SwingWorker<Integer, Integer>
{
    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();
        }
    }
}

doInBackgroundget方法的返回类型被指定为SwingWorker的第一种类型,第二种类型是用于返回publish的类型}和process方法,在本例中未使用。

然后,为了调用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);
}

运行应用程序后,会有两个按钮。一个标有“答案!”和另一个“没什么”。当点击“答案!”时按钮,一开始什么都不会发生,但点击“Nothing”按钮将起作用,并证明GUI是响应式的。

一秒钟之后,AnswerWorker的结果将显示在消息框中。

答案 1 :(得分:7)

同意:

  

在事件调度线程(EDT)上运行长时间运行的任务可能导致GUI锁定。

不同意:

  

所以做的一件事就是使用SwingUtilities.invokeLater和invokeAndWait来保持GUI的响应......

invokeLater仍然在EDT上运行代码,并且可以冻结你的UI!试试这个:

SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(100000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

至少我,一旦我点击触发上述代码的actionPerformed的按钮,就无法移动我的鼠标。我错过了什么吗?