2017-09-14 13 views
0

私はかなり新しいスレッドで、長い時間Javaを書いていないので、ここで私に同行してください。私は非常にシンプルなGUIを持っています。それは、カウンター、ステータスラベル、開始と停止の2つのボタンをそれぞれ持っています。スレッドを使ったGUIの更新

私がしたいことは、counterスレッドを使用してステータスラベルを更新することでした。私が起動すると、カウンタは0で始まり、毎回secondをインクリメントします。stopを選択すると、現在のスレッドはsuspend、開始ボタンはwaitになるはずです。しかし、私が停止するたびに、それはちょうど2秒待ってからカウントを再開します。現実には私はそれを中断したままにしたい。なぜそれがやっているのか分からず、ここに掲示する前にそれを探してみましたが、何も見つかりませんでした。また、あなたが好きなものを批判することも自由です。ここで

は、私が持っているものです。

はPER @ MadProgrammerの答えとして更新しました。基本的には

import java.awt.Font; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import static javax.swing.JFrame.EXIT_ON_CLOSE; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 

public class main extends JFrame 
{ 


    JLabel countLabel = new JLabel("0"); 
    JLabel statusLabel = new JLabel("Task not completed."); 
    JButton startButton = new JButton("Start"); 
    JButton stopButton = new JButton("Stop"); 
    CounterThread worker = new CounterThread("worker", countLabel, statusLabel); 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new Main("Counter Demo"); 
      } 
     }); 
    } 

    public Main(String title) { 
     super(title); 

     setLayout(new GridBagLayout()); 

     countLabel.setFont(new Font("serif", Font.BOLD, 28)); 

     GridBagConstraints gc = new GridBagConstraints(); 

     gc.fill = GridBagConstraints.NONE; 

     gc.gridx = 0; 
     gc.gridy = 0; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(countLabel, gc); 

     gc.gridx = 0; 
     gc.gridy = 1; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(statusLabel, gc); 

     gc.gridx = 0; 
     gc.gridy = 2; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(startButton, gc); 

     gc.gridx = 0; 
     gc.gridy = 3; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(stopButton, gc); 

     startButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       worker.start(); 
       //notify(); 
      } 
     }); 
     stopButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       worker.suspend(); 
      } 
     }); 
     setSize(200, 400); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setVisible(true); 
    } 

public class CounterThread implements Runnable { 

    public Thread t; 
    public String threadName; 
    boolean suspended = false; 
    JLabel countLabelName; 
    JLabel statusLabelName; 

    CounterThread(String name, JLabel cLabel, JLabel sLabel) { 
     this.threadName = name; 
     this.countLabelName = cLabel; 
     this.statusLabelName = sLabel; 
    } 

    public void run() { 
     try { 
      // Simulate doing something useful. 
      for (int i = 0; i <= 10; i++) { 
       synchronized (this) { 
        if (suspended) 
        {    
         wait(); 
        } 
       } 
       final int count = i; 

       SwingUtilities.invokeLater(new Runnable() { 
        public void run() { 
         countLabelName.setText(Integer.toString(count)); 
        } 
       }); 
       Thread.sleep(1000); 
      } 
     } catch (InterruptedException e) { 
     } 

     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       statusLabelName.setText("Completed."); 
      } 
     }); 

     this.start(); 
    } 

    public boolean getStatus() { 
     return t == null; 
    } 

    public void start() { 
     if (getStatus()) { 
      //t = new Thread(new CounterThread(this.threadName, this.countLabelName, this.statusLabelName)); 
      t = new Thread(this); 
      t.start(); 
     } 
    } 

    public void suspend() { 
     statusLabelName.setText("Task is paused"); 
     suspended = true; 
    } 
    //create an object whose only purpose is to synchronize 

    synchronized void resume() { 
     statusLabelName.setText("Task has resumed"); 
     suspended = false; 
     this.notify(); 
    } 

} 
} 
+0

あなたの最善の策は、スイングとOracleのチュートリアルをスレッドを確認し、インポートしているそのうちのいくつかは、関連するスイングユーティリティクラスを、チェックアウトすることで、すべての世話の問題をオフに再開しますしかし、決して使用しないでください。同様に、あなたはjava.util.concurrentを認識しているように見えますが、それを使用していません。同期プリミティブ、 'notify'などを直接使うのは避けてください。コードとインデントを整理します。実行可能クラスを実装してスレッドを含み、スレッドを開始するクラスがあります。あなたも。 – pvg

+0

バックグラウンドで特別な処理が必要な場合を除き、代わりにSwing 'Timer'を使ってみることをお勧めします。 – MadProgrammer

+0

' boolean suspended = false; 'はおそらく' volatile'とマークされるべきです'' AtomicBoolean') – MadProgrammer

答えて

0

...

synchronized(this) 
{ 
    if(suspended) 
    { 
     if(getStatus()) 
      wait(); 
     resume(); 
    } 
} 

getStatus

は、私はこれをチェックする必要がある理由は本当にわからないので t != null

ので、それは(wait呼び出しをスキップしていますfalseを返すが、私れますenumや、より意味のある状態を返す他のフラグ(RUNNINGSTOPPEDPAUSED ...これまでのもの)

私の代わりに...

synchronized(this) 
{ 
    if(suspended) 
    { 
     wait(); 
    } 
} 

それは何かなどを行うことによって動作させることができました。

しかしそれは言いました。私は個人的にあなたのためのすべてのこの仕事をするだろうし、それはでも、それはだあなたの提案の答えを

を変更された元のコードの後に​​更新EDT

のコンテキスト内で更新をだトリガーするスイングTimerを使用して検討したいですそれでも同じように動作し、それが

t = new Thread(new CounterThread(this.threadName, this.countLabelName, this.statusLabelName)); 
を追加し、簡単な第二のためにそれを中断し、すぐにあなたがオリジナルのポストからのコードを変更し

再開します

startメソッドのUIコードには、すでに相互作用しているCounterThreadへの参照が含まれています。そのため、同じクラスの2つのインスタンスがあります。バックグラウンドで実行中のUIコードとUIコードと対話する。

UIがsuspendを呼び出したときに、それはまた、実際に

import java.awt.Font; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import static javax.swing.JFrame.EXIT_ON_CLOSE; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 

public class Main extends JFrame { 

    JLabel countLabel = new JLabel("0"); 
    JLabel statusLabel = new JLabel("Task not completed."); 
    JButton startButton = new JButton("Start"); 
    JButton stopButton = new JButton("Stop"); 
    int holder; 
    CounterThread worker = new CounterThread("worker", countLabel, statusLabel); 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new Main("Counter Demo"); 
      } 
     }); 
    } 

    public Main(String title) { 
     super(title); 

     setLayout(new GridBagLayout()); 

     countLabel.setFont(new Font("serif", Font.BOLD, 28)); 

     GridBagConstraints gc = new GridBagConstraints(); 

     gc.fill = GridBagConstraints.NONE; 

     gc.gridx = 0; 
     gc.gridy = 0; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(countLabel, gc); 

     gc.gridx = 0; 
     gc.gridy = 1; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(statusLabel, gc); 

     gc.gridx = 0; 
     gc.gridy = 2; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(startButton, gc); 

     gc.gridx = 0; 
     gc.gridy = 3; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(stopButton, gc); 

     startButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       worker.start(); 
      } 

     }); 

     stopButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       worker.suspend(); 
      } 
     }); 
     setSize(200, 400); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setVisible(true); 
    } 

    public class CounterThread implements Runnable { 

     public Thread t; 
     public String threadName; 
     boolean suspended = false; 
     JLabel countLabelName; 
     JLabel statusLabelName; 

     CounterThread(String name, JLabel cLabel, JLabel sLabel) { 
      this.threadName = name; 
      this.countLabelName = cLabel; 
      this.statusLabelName = sLabel; 
     } 

     public void run() { 
      try { 
       // Simulate doing something useful. 
       for (int i = 0; i <= 10; i++) { 
        synchronized (this) { 
         if (suspended) { 
          wait(); 
         } 
        } 
        final int count = i; 

        SwingUtilities.invokeLater(new Runnable() { 
         public void run() { 
          countLabelName.setText(Integer.toString(count)); 
         } 
        }); 

        Thread.sleep(1000); 

       } 
      } catch (InterruptedException e) { 
      } 

      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        statusLabelName.setText("Completed."); 
       } 
      }); 

      this.start(); 
     } 

     public boolean getStatus() { 
      return t == null; 
     } 

     public void start() { 
      if (getStatus()) { 
       //t = new Thread(new CounterThread(this.threadName, this.countLabelName, this.statusLabelName)); 
       t = new Thread(this); 
       t.start(); 
      } 
     } 

     public void suspend() { 
      statusLabelName.setText("Task is paused"); 
      suspended = true; 
     } 
     //create an object whose only purpose is to synchronize 

     synchronized void resume() { 
      statusLabelName.setText("Task has resumed"); 
      suspended = false; 
      this.notify(); 
     } 

    } 
} 

を実行しているインスタンスのsuspended状態を変更していないので、私はスイングタイマーを使用すると、この中で私を助ける方法を見ていません待機

のための実際の遅延はありませんので、場合、その後、あなたは明らかにTimer

をどのように機能するかを理解していません
import java.awt.Font; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import static javax.swing.JFrame.EXIT_ON_CLOSE; 
import javax.swing.JLabel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

public class Main extends JFrame { 

    JLabel countLabel = new JLabel("0"); 
    JLabel statusLabel = new JLabel("Task not completed."); 
    JButton startButton = new JButton("Start"); 
    JButton stopButton = new JButton("Stop"); 
    int holder; 

    Timer timer; 
    int count = 0; 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new Main("Counter Demo"); 
      } 
     }); 
    } 

    public Main(String title) { 
     super(title); 

     setLayout(new GridBagLayout()); 

     countLabel.setFont(new Font("serif", Font.BOLD, 28)); 

     GridBagConstraints gc = new GridBagConstraints(); 

     gc.fill = GridBagConstraints.NONE; 

     gc.gridx = 0; 
     gc.gridy = 0; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(countLabel, gc); 

     gc.gridx = 0; 
     gc.gridy = 1; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(statusLabel, gc); 

     gc.gridx = 0; 
     gc.gridy = 2; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(startButton, gc); 

     gc.gridx = 0; 
     gc.gridy = 3; 
     gc.weightx = 1; 
     gc.weighty = 1; 
     add(stopButton, gc); 

     timer = new Timer(1000, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       count++; 
       countLabel.setText(Integer.toString(count)); 
      } 
     }); 

     startButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       timer.start(); 
      } 

     }); 

     stopButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       if (timer.isRunning()) { 
        timer.stop(); 
        stopButton.setText("Resume"); 
       } else { 
        timer.restart(); 
        stopButton.setText("Stop"); 
       } 
      } 
     }); 
     setSize(200, 400); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setVisible(true); 

    } 
} 

は今、そこに一時停止があると

+0

私は、' return t == null'私にスレッドの状態を返してください。別名RUNNING、STOPPED。あなたの提案された答えでも、それは同じように動作しています。すぐに中断してすぐに再開します –

+0

あなたは元の投稿からコードを変更しました。 'start'メソッドでは' t = new Thread(新しいCounterThread(this.threadName、this.countLabelName、this.statusLabelName)); 'を実行していますが、UIコードが別のインスタンスと対話しています - ' CounterThread worker = new CounterThread( "worker"、countLabel、statusLabel); '実際にスレッドを実行しているコードを変更する方法はありません(名前を変更しました) – MadProgrammer

+0

少なくとも今は中断しています。スタートボタンをもう一度押すと 'notify 'を使ってカウンタを再開する方法また、スイングタイマーを使用すると、この場合はどのように役立つのかわかりません。待ち時間が実際に遅れることはないためです。私は単に開始ボタンが再度クリックされるまで待っている。 –

関連する問題