如何在Java中使用SwingWorker?

Rel*_*ual 44 java swingworker

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

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

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

coo*_*ird 108

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

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

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

Java Tutorial有一个关于SwingWorker的部分.

下面是一个示例,其中a 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

返回类型doInBackgroundget方法被指定为第一种类型,SwingWorker第二种类型是用于返回publishprocess方法的类型,在本例中未使用.

然后,为了调用SwingWorker,调用该execute方法.在这个例子中,我们将挂钩ActionListenera JButton来执行AnswerWorker:

JButton b = new JButton("Answer!");
b.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e)
    {
        new AnswerWorker().execute();
    }
});
Run Code Online (Sandbox Code Playgroud)

可以将上面的按钮添加到a 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);
}
Run Code Online (Sandbox Code Playgroud)

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

并且,一秒钟之后,该结果AnswerWorker将出现在消息框中.


dal*_*ez1 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();
                }
            }
        });
Run Code Online (Sandbox Code Playgroud)

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