Как я могу использовать SwingWorker в Java? - PullRequest
42 голосов
/ 23 апреля 2009

В связи с моим предыдущим вопросом: Вызовите перерисовку из другого класса в Java?

Я новичок в Java и ознакомился с некоторыми учебными пособиями по SwingWorker. Тем не менее, я не уверен, как реализовать это с помощью примера кода, который я дал в предыдущем вопросе.

Может ли кто-нибудь объяснить, как использовать SwingWorker в отношении моего фрагмента кода, и / или указать мне на достойное руководство? Я посмотрел, но пока не уверен, что понимаю.

Ответы [ 2 ]

105 голосов
/ 23 апреля 2009

Обычно SwingWorker используется для выполнения долгосрочных задач в Swing.

Выполнение долгосрочных задач в потоке диспетчеризации событий (EDT) может привести к блокировке графического интерфейса, поэтому было сделано только одно из следующих действий: SwingUtilities.invokeLater и invokeAndWait, который поддерживает реагирование графического пользовательского интерфейса, который определяет приоритет других событий AWT перед запуском требуемой задачи (в форме Runnable).

Однако проблема с SwingUtilities заключается в том, что он не позволяет возвращать данные из выполненного Runnable в исходный метод. Это то, что SwingWorker было предназначено для решения.

В руководстве по Java есть раздел, посвященный 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();
        }
    }
}

Тип возврата методов doInBackground и get указывается как первый тип 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 можно использовать следующее:

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

После запуска приложения появятся две кнопки. Один с надписью "Ответ!" и еще одно «Ничего». Когда один нажимает на «Ответить!» кнопка, сначала ничего не произойдет, но нажатие на кнопку «Ничего» будет работать и продемонстрирует, что графический интерфейс отзывчив.

И через секунду результат AnswerWorker появится в окне сообщения.

7 голосов
/ 12 июля 2013

Согласитесь:

Запуск длительных задач в потоке диспетчеризации событий (EDT) может привести к блокировке графического интерфейса.

Не согласен:

поэтому одна из вещей, которые были сделаны, - это использовать SwingUtilities.invokeLater и invokeAndWait, которые поддерживают отзывчивость графического интерфейса ..

invokeLater по-прежнему выполняет код на EDT и может заморозить ваш пользовательский интерфейс !! Попробуйте это:

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

По крайней мере, я не могу двигать мышью после нажатия кнопки, которая запускает действие, выполненное с помощью приведенного выше кода. Я что-то упустил?

...