如何消除keyPress的延迟?

所以我已经看到了一些关于这个的线程,我需要一些关于如何具体修复它的帮助。 当您按住某个键时,Java将读取第一个按键,然后会有一个小的延迟,然后它将连续读取按键,直到您释放该键。

public void keyPressed(KeyEvent key) { int code = key.getKeyCode(); if (code == KeyEvent.VK_DOWN) { //Do stuff } if (code == KeyEvent.VK_LEFT) { //Do stuff } if (code == KeyEvent.VK_RIGHT) { //Do stuff } if (code == KeyEvent.VK_UP) { //Do stuff } } 

那是我目前的代码。 我听说要解决这个问题,你可以创建一个快速检查按键的计时器,但我不确定该怎么做。 会在这里感谢一些帮助,或者是否有更好的解决方案。

您的问题的基本答案是,您不能,延迟是特定于操作系统的。

答案越长,您应该忽略各个事件本身,并通过使用适当的标志来监控状态的变化(在按下和释放之间)。

这意味着,当按下某个键时,您可以设置一些标志,您可以使用该标志来更改程序的状态,并在释放时重置它。

这解除了事件与状态变化的关联,并为您提供了更大的灵活性,因为您的程序不关心导致状态变化的原因,只是状态已经发生变化并且应该对其做出反应。

这将需要你有一种“循环”,它的责任是监视这种变化并相应地做出反应。 在游戏中,这通常被称为“游戏循环”,但也可称为“主循环”。

这是“循环”的责任,更新程序的状态并绘制它。

下面是一个非常简单的示例,它使用键绑定API和javax.swing.Timer来演示基本概念

 import com.sun.glass.events.KeyEvent; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.AbstractAction; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.KeyStroke; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class MoveMe { public static void main(String[] args) { new MoveMe(); } public MoveMe() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new TestPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class MovementState { public int xDirection; public int yDirection; } public class TestPane extends JPanel { private MovementState movementState; private Rectangle box; public TestPane() { movementState = new MovementState(); InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap am = getActionMap(); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "down-pressed"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "down-released"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "up-pressed"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "up-released"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "left-pressed"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "left-released"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "right-pressed"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "right-released"); am.put("down-pressed", new YDirectionAction(movementState, 2)); am.put("down-released", new YDirectionAction(movementState, 0)); am.put("up-pressed", new YDirectionAction(movementState, -2)); am.put("up-released", new YDirectionAction(movementState, 0)); am.put("left-pressed", new XDirectionAction(movementState, -2)); am.put("left-released", new XDirectionAction(movementState, 0)); am.put("right-pressed", new XDirectionAction(movementState, 2)); am.put("right-released", new XDirectionAction(movementState, 0)); box = new Rectangle(90, 90, 20, 20); Timer timer = new Timer(40, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { box.x += movementState.xDirection; box.y += movementState.yDirection; if (box.x < 0) { box.x = 0; } else if (box.x + box.width > getWidth()) { box.x = getWidth() - box.width; } if (box.y < 0) { box.y = 0; } else if (box.y + box.height > getHeight()) { box.y = getHeight() - box.height; } repaint(); } }); timer.start(); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); g2d.setColor(Color.RED); g2d.fill(box); g2d.dispose(); } } public abstract class AbstractDirectionAction extends AbstractAction { private final MovementState movementState; private final int value; public AbstractDirectionAction(MovementState movementState, int value) { this.movementState = movementState; this.value = value; } public MovementState getMovementState() { return movementState; } public int getValue() { return value; } } public class YDirectionAction extends AbstractDirectionAction { public YDirectionAction(MovementState movementState, int value) { super(movementState, value); } @Override public void actionPerformed(ActionEvent e) { getMovementState().yDirection = getValue(); } } public class XDirectionAction extends AbstractDirectionAction { public XDirectionAction(MovementState movementState, int value) { super(movementState, value); } @Override public void actionPerformed(ActionEvent e) { getMovementState().xDirection = getValue(); } } }