2

私はJavaスイングでコンウェイのライフゲーム問題を実装しました。すべてが正常に機能しています。下のスクリーンショットでわかるように、「ティック」ボタンがクリックされるたびに、ゲームは次の生命体に進みます。今、私は「チェック」ボタンの横に「自動再生」ボタンを含めることを計画しています。この自動再生の目的は単純です。叩くと、1秒間隔でティックボタンを押しているかのように自動操作が続行されます。

ここに画像の説明を入力してください

これを試してみました。しかし、これは他のすべての操作をブロックしているようです。別のスレッドでこのアクションを実行するにはどうすればよいですか?小さなコードスニペットでうまくいきます。

class AutoPlayListener implements ActionListener{
  public void actionPerformed(ActionEvent e) {
    if(e.getSource() == btnAutoPlay){
      while(true){
        Thread.sleep(1000); //InterruptedException try catch hidden
        btnTick.doClick();
      }
    }
  }
}
4

3 に答える 3

6

を使用しjavax.swing.Timerます。および呼び出しが削除されたActionListener場合、既存のものと連携できるようになります。while(true)Thread.sleep()

于 2011-08-08T09:25:25.197 に答える
2

2つのオプションがあります。

  1. 新しいスレッドを開始します。スレッドにはwhileループが含まれ、配列を処理するメソッドを実行します。各反復で、repaint()またはinvalidate()ウィンドウを呼び出して、再描画が必要であることを通知します。
  2. タイマーを使用します。GUIスレッドは、定期的にルーチンを呼び出します。

スレッド:

メソッドで、actionPerformed新しいスレッドを作成します。そして、そのstartメソッドを呼び出します。スレッドのRunnableは、(すでに実行したように)whileループを実行してから、単に終了する必要があります。

タイマー:

タイプTimerのクラスにオブジェクトを作成します。java.swing.Timerスイングを使用している場合は、で1つを使用します( java.util.TimerGUI操作に適さないものもあります)。タイマーActionListenerには、メソッドを1回呼び出すが必要ですが、タイマーの繰り返しレートは1000msです。

チップ

  1. アクションを呼び出すには、ボタンハンドラーのすぐ下ではなく、別のメソッドに配置する必要があります。そうすれば、GUIスレッドの外部からGUIのものを呼び出すことはありません。

例えば

tickButton.addActionListener(new ActionListener(){
  public void actionPerformed(ActionEvent e){
    doTick();
  }
});
  1. スレッドを停止するメカニズムも同様に重要です。一般に、スレッドでaを使用しないでくださいwhile(true)。失われるため、それを終了するためのセマフォを発明します。

  2. JToggleButtonではなくを使用しButtonますか?

  3. 同期:スレッドを使用する場合、ボタンが押されるたびに新しいスレッドが作成されないようにするために、次のようなものが必要になります。

コード

Thread autoplayThread = null;
Object lock;
boolean autoplaying = false;
public void actionPerformed(ActionEvent e){
  synchronized(lock){ // prevent any race condition here
    if(!autoplaying && autoplayThread==null ){
      autoplaying = true; 
      autoplayThread = new Thread(new Runnable(){
        public void run(){
          try{ 
            while(autoplaying){  ....  }
          }finally{
            synchronized(lock) {
              autoplaying=false;
              autoplayThread=null;
            }
          }
        }
      });
      autoplayThread.start();
    }else{ // stop the thread!
      autoplaying=false;
    }
  }
}
于 2011-08-08T09:20:42.873 に答える
2

@Ranmanが言ったように、メインUIスレッドをブロックしています。SwingUtilities.invokeLaterは通常このようなものに使用されると思います

于 2011-08-08T09:23:53.277 に答える