Рубрики
Без рубрики

Как использовать потоки в Java Swing

Автор оригинала: 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
   SwingWorker worker = 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... фрагменты) и процесс(Список фрагментов) .

Ресурсы