51

与我之前的问题相关:从 Java 中的另一个类调用重绘?

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

谁能解释一下如何在我的代码片段中使用 SwingWorker 和/或向我指出一个体面的教程?我看过,但我不确定我是否理解。

4

2 回答 2

115

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

在事件调度线程 (EDT) 上运行长时间运行的任务可能会导致 GUI 锁定,因此已完成的一件事是使用SwingUtilities.invokeLaterinvokeAndWait保持 GUI 响应,从而在运行所需任务之前优先考虑其他 AWT 事件(以 a 的形式Runnable)。

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

Java 教程有一个关于SwingWorker的部分。

这是一个示例,其中 aSwingWorker用于在单独的线程上执行耗时的任务,并在一秒钟后显示一个带有答案的消息框。

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();
        }
    }
}

doInBackground和方法的返回类型get指定为第一种类型,SwingWorker第二种是用于返回的类型publishprocess方法,本例中没有使用。

然后,为了调用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将出现在消息框中。

于 2009-04-23T15:37:27.213 回答
12

同意:

在事件调度线程 (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 的按钮,就无法移动鼠标。我错过了什么吗?

于 2013-07-12T13:42:12.757 回答