首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >暂停timerTask

暂停timerTask
EN

Stack Overflow用户
提问于 2011-10-22 20:52:00
回答 5查看 2.6K关注 0票数 2

我撞到了另一面墙。在让我的按键输入工作后,我已经绞尽脑汁好几个小时了,我想创建一个暂停功能,这样如果再次按下相同的按键,计时器任务就会停止运行(即游戏暂停)

代码语言:javascript
复制
JPanel component = (JPanel)frame.getContentPane();
    component.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "space");
    component.getActionMap().put("space", (new AbstractAction(){
        public void actionPerformed(ActionEvent e){

            Timer timer = new Timer();

            timer.scheduleAtFixedRate(new TimerTask(){
            public void run(){
                    grid.stepGame();
                }
            },250, 250);



        }}));


        }

问题是我不能使用全局布尔型isRunning变量并在每次按下键时切换它,因为嵌套类中的timerTask方法(因此布尔型isRunning必须被声明为isRunning才能被访问...)。关于如何检测是否再次按下键或游戏是否已经运行,以便我可以暂停/取消我的timerTask,有什么想法吗?

非常感谢,山姆

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-10-22 20:54:50

由于这是一个Swing游戏,您应该使用javax.swing.Timer或Swing计时器,而不是java.util.Timer。通过使用Swing计时器,您可以保证在EDT上间歇性调用的代码会被调用,这是Swing应用程序的一个关键问题,而且它还具有暂停计时器的stop方法。您还可以为匿名AbstractAction类提供一个私有的布尔值字段,以检查该键是否是第一次按下。

此外,还有使用键绑定而不是KeyListener的kudos和1+。

例如,

代码语言:javascript
复制
  JPanel component = (JPanel) frame.getContentPane();
  component.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "space");
  component.getActionMap().put("space", (new AbstractAction() {
     private boolean firstPress = true;
     private int timerDelay = 250;
     private javax.swing.Timer keyTimer = new javax.swing.Timer(timerDelay , new ActionListener() {

        // Swing Timer's actionPerformed
        public void actionPerformed(ActionEvent e) {
           grid.stepGame();
        }
     });

     // key binding AbstractAction's actionPerformed
     public void actionPerformed(ActionEvent e) {
        if (firstPress) {
           keyTimer.start();
        } else {
           keyTimer.stop();
        }

        firstPress = !firstPress;
     }
  }));

另一个有用的选择是在按键时执行重复的任务,并在按键释放时停止它,这可以通过在按下和释放时进行击键来轻松完成:

代码语言:javascript
复制
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true) // for key release
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false) // for key press

例如:

代码语言:javascript
复制
import java.awt.event.*;
import javax.swing.*;

public class SwingTimerEg2 {
   private JFrame frame;
   private Grid2 grid = new Grid2(this);
   private JTextArea textarea = new JTextArea(20, 20);
   private int stepCount = 0;

   public SwingTimerEg2() {
      frame = new JFrame();

      textarea.setEditable(false);
      frame.add(new JScrollPane(textarea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
            JScrollPane.HORIZONTAL_SCROLLBAR_NEVER));

      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
      setUpKeyBinding();
   }

   void setUpKeyBinding() {
      final int timerDelay = 250;
      final Timer keyTimer = new Timer(timerDelay, new ActionListener() {

         @Override
         public void actionPerformed(ActionEvent e) {
            grid.stepGame();
         }
      });
      JPanel component = (JPanel) frame.getContentPane();
      final int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
      final String spaceDown = "space down";
      final String spaceUp = "space up";
      component.getInputMap(condition).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, false), spaceDown);
      component.getActionMap().put(spaceDown, (new AbstractAction() {
         public void actionPerformed(ActionEvent e) {
            keyTimer.start();
         }
      }));
      component.getInputMap(condition).put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0, true), spaceUp);
      component.getActionMap().put(spaceUp, (new AbstractAction() {
         public void actionPerformed(ActionEvent e) {
            keyTimer.stop();
         }
      }));

   }

   public void doSomething() {
      textarea.append(String.format("Zap %d!!!%n", stepCount));
      stepCount ++;
   }

   private static void createAndShowGui() {
      new SwingTimerEg2();
   }

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

}

class Grid2 {
   private SwingTimerEg2 stEg;

   public Grid2(SwingTimerEg2 stEg) {
      this.stEg = stEg;
   }

   void stepGame() {
      stEg.doSomething();
   }
}
票数 6
EN

Stack Overflow用户

发布于 2011-10-22 20:54:47

最简单、最肮脏的解决方案:

代码语言:javascript
复制
final boolean[] isRunning = new boolean[1];

你不会想这样做的--但它在假设适当的同步的情况下是有效的。

更好的是

代码语言:javascript
复制
final AtomicBoolean isRunning = new AtomicBoolean();

更好的做法是再次审查设计:全局状态通常意味着“全局问题”。

票数 0
EN

Stack Overflow用户

发布于 2011-10-22 20:57:29

最后一个限定符要求可以很容易地避免--将内部方法(具有final要求)替换为对类方法的调用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7859656

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档