2016-12-20 3 views
0

Есть ли способ постоянно обновлять JLabel внутри цикла из отдельного потока. В настоящий момент Jlabel получает обновление только после завершения цикла.Постоянно обновлять JLabel внутри цикла из отдельного потока

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

Есть ли способ, которым я могу запускать оба потока одновременно?

Я попытался дать Thread.sleep (300) внутри цикла, но не работал.

+2

Конечно, есть. Но без кода трудно сказать, где возникает проблема. – Paul

+1

Попробуйте придумать [mcve]. Но, вероятно, вам просто нужно заглянуть в http://stackoverflow.com/questions/6567870/what-does-swingutilities-invokelater-do ... вы хотите вызвать SwingUtilties.invokeLater(), чтобы обновить эту метку от другой нить. И, конечно же, вы не хотите спать на EDT. – GhostCat

+0

Если вы хотите работать с качелями и избегать кошмаров относительно обновлений пользовательского интерфейса, попробуйте использовать «SwingWorker». Эти потоки дополняются возможностями, которые позволяют выполнять подпольную задачу с возможностью обновления пользовательского интерфейса, не имея необходимости скрываться в нижней части потока диспетчеризации событий (событий Swing Framework). – Victor

ответ

4

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

Это неправильно. Если другой поток действительно отключен от потока событий Swing, оба должны запускаться одновременно. У вас есть ошибка, когда:

  1. Вы думаете, что вы бежите от нити Качели событий, но вы не или
  2. Вы думаете, что вы обновляете GUI на Swing, поток событий, но это не так.

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

например,

import java.awt.BorderLayout; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.util.concurrent.TimeUnit; 

import javax.swing.*; 

@SuppressWarnings("serial") 
public class UpdateLabel extends JPanel { 
    // label to update 
    private JLabel statusLabel = new JLabel(""); 

    public UpdateLabel() { 
     JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 3, 3)); 
     topPanel.add(new JLabel("Counter:")); 
     topPanel.add(statusLabel); 

     JPanel bottomPanel = new JPanel(); 
     bottomPanel.add(new JButton(new StartThreadAction("Start Thread"))); 

     setLayout(new BorderLayout()); 
     add(topPanel, BorderLayout.PAGE_START); 
     add(bottomPanel, BorderLayout.PAGE_END); 
    } 

    // fail safe method that is guaranteed to add text to the label 
    // **on the Swing event thread** 
    public void setLabelText(final String text) { 
     if (SwingUtilities.isEventDispatchThread()) { 
      statusLabel.setText(text); 
     } else { 
      SwingUtilities.invokeLater(() -> { 
       statusLabel.setText(text); 
      }); 
     } 
    } 

    // Abstract Action for our JButton 
    private class StartThreadAction extends AbstractAction { 
     protected static final int MAX_COUNT = 10; 
     protected static final long SLEEP_TIME = 1; 

     public StartThreadAction(String name) { 
      super(name); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      // start a new thread 
      new Thread(new Runnable() { 
       private int counter = 0; 

       @Override 
       public void run() { 
        // within the background thread update a counter and sleep 
        while (counter < MAX_COUNT) { 
         String text = "" + counter; 
         setLabelText(text); // call our fail safe method 
         counter++; 
         try { 
          // sleep for 1 second 
          TimeUnit.SECONDS.sleep(SLEEP_TIME); 
         } catch (InterruptedException e) { 
          // rare time it's OK to leave this blank 
         } 
        } 
       } 
      }).start(); 
     } 
    } 

    private static void createAndShowGui() { 
     UpdateLabel mainPanel = new UpdateLabel(); 

     JFrame frame = new JFrame("UpdateLabel"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     // start GUI on the Swing event thread 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 

Сказав все это, что-то вроде простого подсчета с задержкой, я хотел бы использовать Swing-таймер, потому что нет никаких забот о вызове коды или выключить EDT, так как таймер гарантирует, что все вызовы будут в этой теме.

import java.awt.BorderLayout; 
import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import javax.swing.*; 

@SuppressWarnings("serial") 
public class UpdateLabel2 extends JPanel { 
    // label to update 
    private JLabel statusLabel = new JLabel(""); 
    private Timer timer; 

    public UpdateLabel2() { 
     JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 3, 3)); 
     topPanel.add(new JLabel("Counter:")); 
     topPanel.add(statusLabel); 

     JPanel bottomPanel = new JPanel(); 
     bottomPanel.add(new JButton(new StartTimerAction("Start Timer"))); 

     setLayout(new BorderLayout()); 
     add(topPanel, BorderLayout.PAGE_START); 
     add(bottomPanel, BorderLayout.PAGE_END); 
    } 

    // Abstract Action for our JButton 
    private class StartTimerAction extends AbstractAction { 
     protected static final int MAX_COUNT = 10; 
     private static final int TIMER_DELAY = 1000; // 1 second 
     private int counter = 0; 

     public StartTimerAction(String name) { 
      super(name); 
      putValue(MNEMONIC_KEY, KeyEvent.VK_S); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (timer != null && timer.isRunning()) { 
       return; // wait until timer finishes 
      } 
      timer = new Timer(TIMER_DELAY, new ActionListener() { 

       @Override 
       public void actionPerformed(ActionEvent e2) { 
        if (counter >= MAX_COUNT) { 
         timer.stop(); 
         counter = 0; 
        } else { 
         counter++; 
         statusLabel.setText("" + counter); 
        } 
       } 
      }); 
      timer.start(); 
     } 
    } 

    private static void createAndShowGui() { 
     UpdateLabel2 mainPanel = new UpdateLabel2(); 

     JFrame frame = new JFrame("UpdateLabel"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     // start GUI on the Swing event thread 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
}