java - 我是否正确构建了这个关键监听器?

标签 java swing animation keylistener

我这么问是因为我希望当用户点击 enter 时调用我的 GamePanel 类中的 addShot() 方法,”这初始化了一个代表从船上发射的导弹的射击对象,但它没有做任何事情。这里是否存在可见性问题,或者我只是错误地构建了关键事件和监听器关系?我只发布相关代码,但是如果需要的话我可以发布其余的内容。

代码如下:

public static class GameTest extends JFrame {

    private static final int WINDOW_WIDTH = 800;
    private static final int WINDOW_HEIGHT = 500;
    public GamePanel gamePanel;


    public GameTest() throws IOException {
        super("Deep Fried Freedom");
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
        setLayout(new BorderLayout());
        gamePanel = new GamePanel();
        add(gamePanel);
        center(this);
        setVisible(true);
        this.addKeyListener(new aKeyListener());
        this.setFocusable(true);

    } // end constructor

    public void center(JFrame frame) {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        Point center = ge.getCenterPoint();

        int w = frame.getWidth();
        int h = frame.getHeight();

        int x = center.x - w / 2, y = center.y - h / 2;
        frame.setBounds(x, y, w, h);
        frame.validate();
    }//end of center method  

    public class aKeyListener implements KeyListener {

        @Override
        public void keyTyped(KeyEvent e) {
        }//end empty keyTyped method

        @Override
        public void keyPressed(KeyEvent e) {
            switch (e.getKeyCode()) {
                case KeyEvent.VK_A:
                    Launcher.lRun = -20;
                    gamePanel.move(gamePanel);
                    break;
                case KeyEvent.VK_D:
                    Launcher.lRun = 20;
                    gamePanel.move(gamePanel);
                    break;
                case KeyEvent.VK_ENTER:
                        gamePanel.addShot();
                    break;
                default:
                    Launcher.lRun = 0;
            }

        }//end keyPressed method

        @Override
        public void keyReleased(KeyEvent e) {
        }//end empty keyReleased method

    }//end aKeyListener class

}//end GameTest class

最佳答案

  1. 您的问题可能是焦点问题 - GamePanel 中的某些内容可能会窃取焦点,这是 KeyListener 的非常常见问题。
  2. 一般建议:对于此类需求,倾向于使用键绑定(bind),而不是 KeyListener。

有用的链接:

<小时/>

编辑
例如:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class GameTest extends JFrame {

   private static final int WINDOW_WIDTH = 800;
   private static final int WINDOW_HEIGHT = 500;
   public GamePanel gamePanel;

   public GameTest() {
      super("Deep Fried Freedom");
      setResizable(false);
      // setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      // setSize(WINDOW_WIDTH, WINDOW_HEIGHT); // never do this
      gamePanel = new GamePanel();
      setUpKeyBinding(gamePanel);
      add(gamePanel);
      pack();
      setLocationRelativeTo(null); // to center!
      setVisible(true);
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT);
   }

   private void setUpKeyBinding(GamePanel gamePanel2) {

      // only need window to have focus 
      int condition = JComponent.WHEN_IN_FOCUSED_WINDOW; 

      // get the GamePanel's InputMap and ActionMap as these will be used to set
      // up our Key Bindings
      InputMap inputMap = gamePanel2.getInputMap(condition);
      ActionMap actionMap = gamePanel2.getActionMap();

      // bind the A key to move back 20 pixels
      KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0);
      inputMap.put(keyStroke, keyStroke.toString());
      actionMap.put(keyStroke.toString(), new MoveAction(gamePanel2, -20));

      // bind the D key to move forward 20 pixels
      keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_D, 0);
      inputMap.put(keyStroke, keyStroke.toString());
      actionMap.put(keyStroke.toString(), new MoveAction(gamePanel2, 20));

      // bind the ENTER key
      keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);
      inputMap.put(keyStroke, keyStroke.toString());
      actionMap.put(keyStroke.toString(), new EnterAction(gamePanel2));

   }

   public static void main(String[] args) {
      new GameTest();
   }

   // our Action classes that will bound to key strokes
   private class MoveAction extends AbstractAction {
      private GamePanel gamePanel2;
      private int distance;

      public MoveAction(GamePanel gamePanel2, int distance) {
         this.gamePanel2 = gamePanel2;
         this.distance = distance;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         gamePanel2.moveItem(distance);
      }
   }

   private class EnterAction extends AbstractAction {
      private GamePanel gamePanel2;

      public EnterAction(GamePanel gamePanel2) {
         this.gamePanel2 = gamePanel2;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         gamePanel2.addShot();
      }
   }

}

// a trivial GamePanel class to just show that everything is working as expected
class GamePanel extends JPanel {

   public void moveItem(int i) {
      // your moveItem method will instead actually move something, a distance of i
      System.out.println("Move Item Method distance: " + i);
   }

   public void addShot() {
      // your addShot method will actually shoot
      System.out.println("Add Shot Method");
   }

}

关于java - 我是否正确构建了这个关键监听器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23254166/

相关文章:

java - 有没有办法通过 Hibernate 观察数据库表的变化?

Java Tilemaps 使用 Cliping 来提高帧速率 : What can go WRONG?

java - 如何清除android中的动画?

javascript - jquery animate 不流畅

java - 如何让我的 JButtons 位于左侧而不是中间

objective-c - Mac OS X 的 CADisplayLink 替代品

java - 尝试使用 CommandBox 启动服务器时出现 "GTK+ 2.x symbols detected."错误

java.lang.NoClassDefFoundError : org/apache/commons/vfs/FileSystemException

java - 为每个应用程序创建的每个jvm,这是一个线程还是一个进程

java - 自定义 JMenuItem