在java中检测多个按键

我正在尝试制作一个平台,但我坚持如何一次检测多个按键。 例如,如果我使用运行键并向前运行,然后我点击跳转键,游戏仍然需要知道是否正在按下运行键

这比我正常做的更复杂。 通常我会允许每个Action直接改变游戏状态。

此示例显示如何使用键绑定 API监视某些键的按下/释放,并从中央池添加/删除它们。

使用此API的主要原因是它在焦点上下文时克服了KeyListener的限制。 只要窗口具有焦点,此示例将检索按键的通知。

 public class TestMultyKeyPress { public static void main(String[] args) { new TestMultyKeyPress(); } public TestMultyKeyPress() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new KeyPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class KeyPane extends JPanel implements KeyManager { private TrianglePane upPane; private TrianglePane downPane; private TrianglePane leftPane; private TrianglePane rightPane; private List keysList = new ArrayList<>(25); public KeyPane() { setLayout(new GridBagLayout()); upPane = new TrianglePane(0); leftPane = new TrianglePane(1); downPane = new TrianglePane(2); rightPane = new TrianglePane(3); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 0; add(upPane, gbc); gbc.gridx = 0; gbc.gridy++; add(leftPane, gbc); gbc.gridx += 2; add(rightPane, gbc); gbc.gridx = 1; gbc.gridy++; add(downPane, gbc); InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap am = getActionMap(); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "KeyPressed.Left"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "KeyPressed.Right"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "KeyPressed.Up"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "KeyPressed.Down"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "KeyReleased.Left"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "KeyReleased.Right"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "KeyReleased.Up"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "KeyReleased.Down"); am.put("KeyPressed.Left", new KeyAction(KeyEvent.VK_LEFT, false, this)); am.put("KeyPressed.Right", new KeyAction(KeyEvent.VK_RIGHT, false, this)); am.put("KeyPressed.Up", new KeyAction(KeyEvent.VK_UP, false, this)); am.put("KeyPressed.Down", new KeyAction(KeyEvent.VK_DOWN, false, this)); am.put("KeyReleased.Left", new KeyAction(KeyEvent.VK_LEFT, true, this)); am.put("KeyReleased.Right", new KeyAction(KeyEvent.VK_RIGHT, true, this)); am.put("KeyReleased.Up", new KeyAction(KeyEvent.VK_UP, true, this)); am.put("KeyReleased.Down", new KeyAction(KeyEvent.VK_DOWN, true, this)); } @Override public void keyPressed(int keyCode) { if (!keysList.contains(keyCode)) { keysList.add(new Integer(keyCode)); updateKeyState(); } } @Override public void keyReleased(int keyCode) { keysList.remove(new Integer(keyCode)); updateKeyState(); } public void updateKeyState() { upPane.setActive(keysList.contains(KeyEvent.VK_UP)); downPane.setActive(keysList.contains(KeyEvent.VK_DOWN)); leftPane.setActive(keysList.contains(KeyEvent.VK_LEFT)); rightPane.setActive(keysList.contains(KeyEvent.VK_RIGHT)); } } public interface KeyManager { public void keyPressed(int keyCode); public void keyReleased(int keyCode); } public class KeyAction extends AbstractAction { private int keyCode; private boolean released; private KeyManager manager; public KeyAction(int keyCode, boolean released, KeyManager manager) { this.keyCode = keyCode; this.released = released; this.manager = manager; } @Override public void actionPerformed(ActionEvent e) { if (released) { manager.keyReleased(keyCode); } else { manager.keyPressed(keyCode); } } } public class TrianglePane extends JPanel { private boolean active; private TriangleShape shape; public TrianglePane(int direction) { shape = new TriangleShape(20); AffineTransform at = null; switch (direction) { case 0: at = AffineTransform.getRotateInstance(Math.toRadians(-90), 10, 10); // UP break; case 1: at = AffineTransform.getRotateInstance(Math.toRadians(180), 10, 10); // UP break; case 2: at = AffineTransform.getRotateInstance(Math.toRadians(90), 10, 10); // UP break; case 3: at = AffineTransform.getRotateInstance(Math.toRadians(0)); // UP break; } shape.transform(at); } @Override public Dimension getPreferredSize() { return new Dimension(20, 20); } public void setActive(boolean value) { if (active != value) { this.active = value; repaint(); } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); int x = (getWidth() - shape.getBounds().width) / 2; int y = (getHeight() - shape.getBounds().height) / 2; if (active) { g2d.setColor(Color.BLACK); } else { g2d.setColor(Color.GRAY); } g2d.fill(shape); } } public class TriangleShape extends Path2D.Float { public TriangleShape(int size) { moveTo(1, 1); lineTo(size - 1, (size - 1) / 2); lineTo(1, size - 1); closePath(); } } } 

试试这个自定义类,它使用HashSet来跟踪按下的键…

 class MultiKeyPressListener implements KeyListener { // Set of currently pressed keys private final Set pressed = new HashSet(); @Override public synchronized void keyPressed(KeyEvent e) { pressed.add(e.getKeyChar()); if (pressed.size() > 1) { // More than one key is currently pressed. // Iterate over pressed to get the keys. } } @Override public synchronized void keyReleased(KeyEvent e) { pressed.remove(e.getKeyChar()); } @Override public void keyTyped(KeyEvent e) {/* Not used */ } }