Автор оригинала: Scott Robinson.
Программирование непросто, и добавление пользовательского интерфейса вокруг функциональности действительно может усложнить жизнь. Тем более, что не все фреймворки пользовательского интерфейса потокобезопасны (включая Swing). Итак, как мы эффективно обрабатываем пользовательский интерфейс, запускаем рабочий код и передаем данные между ними, сохраняя при этом пользовательский интерфейс отзывчивым?
К счастью для пользователей Swing, есть несколько вариантов, оба из которых могут значительно упростить программирование графических интерфейсов. Есть два из этих вариантов.
Вызовите Позже
SwingUtilities.invokeLater()
отлично подходит для обновления пользовательского интерфейса из другого потока. Возможно, у вас есть длительная задача, и вы хотели бы обновить индикатор выполнения, чтобы предоставить обратную связь пользователю. Вы могли бы попробовать что-то вроде этого:
startButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { progressBar.setValue(0); progressBar.setStringPainted(true); // Runs outside of the Swing UI thread new Thread(new Runnable() { public void run() { for (i = 0; i <= 100; i++) { // Runs inside of the Swing UI thread SwingUtilities.invokeLater(new Runnable() { public void run() { progressBar.setValue(i); } }); try { java.lang.Thread.sleep(100); } catch(Exception e) { } } } }).start(); } });
Надеюсь, вы сможете увидеть из этого примера, как вы могли бы использовать SwingUtilities.invokeLater()
для связи между пользовательским интерфейсом и рабочими потоками. Вы можете думать о invokeLater
как о простом обратном вызове пользовательского интерфейса для отправки любых обновлений, которые вам нужны.
Качающийся Рабочий
SwingWorker
может использоваться аналогично invokeLater
, но у каждого есть свои сильные стороны. Лично я предпочитаю использовать SwingWorker
для длительных задач, для которых мне не нужно обновлять пользовательский интерфейс (например, для загрузки большого документа), в то время как invokeLater
может больше использоваться для длительных задач, для которых требуется обновить пользовательский интерфейс. SwingWorker
может быть использован таким образом с:
private Document doc; JButton button = new JButton("Open XML"); button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // All code inside SwingWorker runs on a seperate thread SwingWorkerworker = new SwingWorker () { @Override public Document doInBackground() { Document intDoc = loadXML(); return intDoc; } @Override public void done() { try { doc = get(); } catch (InterruptedException ex) { ex.printStackTrace(); } catch (ExecutionException ex) { ex.printStackTrace(); } } }; // Call the SwingWorker from within the Swing thread worker.execute(); } });
Этот класс разбивает рабочие события на методы, которые могут быть реализованы в зависимости от ваших потребностей. Для более расширенного использования ознакомьтесь с методами публикация(V... фрагменты)
и процесс(Список фрагментов)
.