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

Программировать непросто, а добавление пользовательского интерфейса к функциональности действительно может усложнить жизнь. Тем более, что не все UI-фреймворки являются потокобезопасными (включая Swing). Итак, как мы можем эффективно обрабатывать пользовательский интерфейс, запускать рабочий код и обмениваться данными между ними, сохраняя при этом отзывчивость пользовательского интерфейса? К счастью для пользователей Swing, есть несколько вариантов, которые могут значительно упростить программирование графического интерфейса пользователя. Вот два из этих вариантов. Вызвать позже SwingUtilities.invokeLater () - это

Программировать непросто, а добавление пользовательского интерфейса к функциональности действительно может усложнить жизнь. Тем более, что не все UI-фреймворки являются потокобезопасными (включая 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<T,V> можно использовать аналогично 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<Document, Void> worker = new SwingWorker<Document, Void>() { 
 @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(); 
 } 
 }); 

Этот класс разбивает рабочие события на методы, которые могут быть реализованы в зависимости от ваших потребностей. Для более продвинутого использования ознакомьтесь с методами publish(V... chunks) и process(List<V> chunks)

Ресурсы

comments powered by Disqus

Содержание