2016-12-20 4 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

スイングで作業し、UIの更新に関する悪夢を避けたい場合は、 "SwingWorker"を試してみてください。これらのスレッドには、(Swing Frameworkの)イベントディスパッチスレッドの底に潜入しなければならないUIを更新する機能を備えた地下タスクを実行できる機能が追加されています。 – Victor

答えて

4

私が間違っている場合は、私には間違いがないと修正してください。これは、他のスレッドが実行を終了するまでイベントディスパッチャスレッドが停止しているためです。

これは間違っています。他のスレッドが本当にSwingイベントスレッドから実行されている場合は、両方とも同時に実行する必要があります。

  1. あなたはスイングイベントスレッドのオフに実行していると思いますが、あなたはあなたがスイングにGUIを更新していることを考えていないですか
  2. :あなたはバグのいずれかを持っていますイベントスレッドが、あなたはそうではありません。

ボトムラインは、表示されていないコードにバグがあり、より適切な回答を表示するために適切なコードを表示することです。

例えば、

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

はすべてこの、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()); 
    } 
} 
関連する問題