如何以编程方式调用作为独立任务运行的按钮?

时间:2011-08-08 09:14:21

标签: java swing conways-game-of-life

我在Java swing中实现了Conway's Game of Life问题。一切都很好。正如您在下面的屏幕截图中看到的,只要单击“勾选”按钮,游戏就会进入下一个生命形式。现在,我计划在“Tick”按钮旁边添加一个“Autoplay”按钮。这种自动播放的目的很简单。当我点击它时,应该继续进行自动操作,就好像我以1秒的间隔按下勾选按钮。

enter image description here

我试过这个。但这似乎阻止了所有其他操作。如何在单独的线程中执行此操作?一个小代码片段会让我走。

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

3 个答案:

答案 0 :(得分:6)

使用javax.swing.Timer。如果删除ActionListenerwhile(true)来电,则可以使用现有的Thread.sleep()

答案 1 :(得分:2)

有两种选择:

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

    actionPerformed方法中,创建一个新线程。并调用其启动方法。 线程的Runnable应该运行一个while循环(就像你已经完成的那样),然后只需退出。

    定时器:

    在类型为Timer的类中创建一个对象。如果使用swing,请使用java.swing.Timer中的那个(还有java.util.Timer,这对GUI操作不利)。计时器应该有ActionListener调用你的方法一次,但Timer的重复率为1000ms。

    提示

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

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

      2. 使用JToggleButton而不是Button

      3. 同步:  如果你使用线程,你将需要这样的东西,以防止每次按下按钮时创建新线程:

      4. 代码

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

答案 2 :(得分:2)

正如@Ranman所说,你正在阻止主UI线程。我相信SwingUtilities.invokeLater通常用于这样的事情。