2

我已经在 J​​ava swing 中实现了 Conway 的生命游戏问题。一切正常。正如您在下面的屏幕截图中看到的那样,只要单击“Tick”按钮,游戏就会进入下一个生命形式。现在,我计划在“勾选”按钮旁边添加一个“自动播放”按钮。这种自动播放的目的很简单。当我点击它时,自动操作应该会继续进行,就好像我每隔 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

有两种选择:

  1. 开始一个新线程。该线程将包含 while 循环,并执行处理数组的方法。在每次迭代中,调用repaint()invalidate()在您的窗口上告诉它需要重绘。
  2. 使用计时器。GUI 线程将定期调用您的例程。

主题:

actionPerformed方法中,创建一个新线程。并调用它的 start 方法。线程的Runnable应该运行一个while循环(正如您已经完成的那样),然后简单地退出。

定时器:

在您的 Timer 类型的类中创建一个对象。java.swing.Timer如果您使用的是 swing(也有java.util.Timer一个不适合 GUI 操作),请使用其中的一个。计时器应该有一个ActionListener调用你的方法一次,但计时器的重复率为 1000 毫秒。

提示

  1. 要调用该操作,您应该将它放在一个单独的方法中,而不是直接放在按钮处理程序下。这样,您就不会从 GUI 线程外部调用 GUI 内容。

例如

tickButton.addActionListener(new ActionListener(){
  public void actionPerformed(ActionEvent e){
    doTick();
  }
});
  1. 停止线程的机制同样重要!一般来说,不要while(true)在线程中使用 a ,因为它会丢失;发明一个信号量来终止它。

  2. 使用 aJToggleButton而不是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 回答