2017-11-03 35 views
0

もう一度教えてください! 次のコードでは、ボタンのプッシュでタイマースレッドを押してラベルに入力することから始めたいと考えています。ボタンを押すたびに新しいスレッドが開始され、各ラベルにそのスレッドをマークする必要があります。しかし残念なことに、各ラベルに同じタイマーが書き込まれます。私たちがそれを正しくするのを助けることができますか?間違いを教えていただけたら、どういう意味ですか?マルチスレッドタイマーが正しく機能しない

public class TimerThreads implements ActionListener{ 

    JFrame jFrame = new JFrame(); 
    JLabel[] labels; 
    int second = 0; 
    int minute = 0; 
    String s = ""; 
    String m = ""; 
    int l = 0; 


    public TimerThreads(){ 
     JLabel one = new JLabel(); 
     JLabel two = new JLabel(); 
     JLabel three = new JLabel(); 
     JLabel four = new JLabel(); 
     labels = new JLabel[]{one, two, three, four}; 

     jFrame.setLayout(new GridLayout(0, 2, 5, 5)); 
     jFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

     JButton start = new JButton("Start"); 
     start.addActionListener(this); 

     JButton stop = new JButton("Stop"); 
     stop.addActionListener(this); 

     jFrame.add(start); 
     jFrame.add(stop); 
     jFrame.setVisible(true); 
     jFrame.pack(); 
    } 

    public static void main(String[] args) { 
     new TimerThreads(); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     String select = e.getActionCommand(); 
     switch(select){ 
      case "Start": 
       jFrame.add(labels[l]); 
       jFrame.revalidate(); 
       jFrame.repaint(); 
       TimerThread t = new TimerThread(labels[l]); 
       t.start(); 
       l++; 
       break; 
      case "Stop": 
       // 
       break; 
     } 
    } 

    class TimerThread extends Thread{ 
     JLabel jLabel; 

     public TimerThread(JLabel jLabel) { 
      this.jLabel = jLabel; 
     } 

     @Override 
     public void run() { 
      Timer timer = new Timer(); 
      timer.scheduleAtFixedRate(new TimerTask() { 
       @Override 
       public void run() { 
        second++; 
        if(String.valueOf(second).length() == 1){ 
         s = "0"; 
        } 
        else{ 
         s = ""; 
        } 
        if(second == 60){ 
         second = 0; 
         s = "0"; 
         minute++; 
        } 

        if(String.valueOf(minute).length() == 1){ 
         m = "0"; 
        } 
        jLabel.setText(m + String.valueOf(minute) + ":" + s + String.valueOf(second)); 
       } 
      },0, 1000); 
     } 
    } 
} 
+1

Swing Timerまたは 'javax.swing.Timer'を使用する必要がある場合は、誤ったTimer、' java.util.Timer'を使用しています。後者のTimerはSwingイベントモデルでうまく動作し、スレッドの衝突を防ぐので、これは非常に重要です。これで問題が解決しない場合は、質問を編集して、スイングタイマーの試行を表示してください。 [Swing Timer Tutorial](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html)を参照してください。 –

+0

その他の主な問題(およびあなたのバグの原因)は、 s、m、second、minuteを含むTimerThreadsクラスのフィールドは、外部のTimerThreadsクラスのフィールドではなく、ネストされたTimerTaskクラスのフィールドである必要があります。これは、すべてのタイマーが同じ値を共有する理由です。 Swing Timerを使用しているはずですが、これらのフィールドはSwing Timer自身のActionListenerフィールド内で宣言する必要があります。 –

+0

彼らが助けてくれてくれてありがとう。私は反応して働いた。 – PengeDroid

答えて

2

バグの原因はここにある:

public class TimerThreads implements ActionListener { 

    JFrame jFrame = new JFrame(); 
    JLabel[] labels; 

    // ***** these fields below 
    int second = 0;  
    int minute = 0; 
    String s = ""; 
    String m = ""; 
    // ***** these fields above 

    int l = 0; 

4つのフィールド

は、クラスのインスタンスフィールドで、作成するすべてのTimerTaskをインスタンスによって共有され、そのすべてが正確に同じが表示されます時間。

ソリューションは、ネストされたクラスに、これらのフィールドは、ローカルにすることです:あなたは間違っているタイマーを使用しているので、


public class TimerThreads implements ActionListener { 

    JFrame jFrame = new JFrame(); 
    JLabel[] labels; 
    // int second = 0; 
    // int minute = 0; 
    // String s = ""; 
    // String m = ""; 
    int l = 0; 

    public TimerThreads() { 
     //..... 
    } 

    // .... 


    class TimerThread extends Thread { 
     JLabel jLabel; 

     public TimerThread(JLabel jLabel) { 
      this.jLabel = jLabel; 
     } 

     @Override 
     public void run() { 
      java.util.Timer timer = new java.util.Timer(); 
      timer.scheduleAtFixedRate(new TimerTask() { 

       // ***** add these fields here 
       int second = 0; 
       int minute = 0; 
       String s = ""; 
       String m = ""; 
はこのことを言って、あなたは、java.utilでの危険なコードを持っています。Timer、Swing Timerまたはjavax.swing.Timerを使用する必要がある場合。後者のTimerはSwingイベントモデルでうまく動作し、スレッドの衝突を防ぐので、これは非常に重要です。 Swing Timer Tutorial

その他の問題:固定サイズの配列を使用すると、ユーザーが4つ以上のスレッドを実行する必要がある場合、インデックスの範囲外の例外が発生する可能性があります。代わりにArrayListを使用してください。

関連する問題