我正在使用Swing开发游戏,我使用KeyBindings从键盘输入。
我遇到了KeyBindings停止响应的问题。每次运行应用程序时都会发生这种情况,但据我所知,当某个事件链发生时,情况并非如此。 KeyBindings只是停止接收来自键盘的输入。我也使用鼠标输入,它继续工作,所以我知道它与输入无关。
我尝试过的一些事情:
KeyListener
代替这些都不起作用。
然后我将项目(不更改任何代码)复制到Windows机器上,经过测试,我无法解决问题。我没有粘贴代码,因为我99%肯定这与我的代码无关,但与其运行的操作系统有关。
这是macOS,JDK for Mac或其他我不了解的问题吗?
我使用的是JDK版本8更新112,计算机正在运行macOS Sierra版本10.12.2。
似乎其他人有same problem我现在做的,但他们从来没有得到答案。
修改
以下是出现问题的代码示例:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
//an example of the problem where the keyboard stops receiving input randomly
public class ProblemExample extends JPanel {
private static final long serialVersionUID = 1L;
private int xPos = 200, yPos = 200;
private boolean wKey, aKey, sKey, dKey;
private BufferedImage image; //sprite
public ProblemExample() {
JFrame frame = new JFrame();
frame.add(this);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
//makes the sprite a red square
image = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB);
int[] redPixels = new int[50 * 50];
for (int i = 0; i < redPixels.length; i++) {
redPixels[i] = 0xffff0000;
}
image.setRGB(0, 0, 50, 50, redPixels, 0, 50);
initializeKeys();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(800, 600);
}
//sets up Key Bindings
private void initializeKeys() {
final String W = "W",
A = "A",
S = "S",
D = "D",
PRESSED = "PRESSED",
RELEASED = "RELEASED";
InputMap inputMap = this.getInputMap(JPanel.WHEN_IN_FOCUSED_WINDOW);
ActionMap actionMap = this.getActionMap();
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), W + PRESSED);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), A + PRESSED);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), S + PRESSED);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), D + PRESSED);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), W + RELEASED);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), A + RELEASED);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), S + RELEASED);
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), D + RELEASED);
Action wActionPressed = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
wKey = true;
}
};
Action aActionPressed = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
aKey = true;
}
};
Action sActionPressed = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
sKey = true;
}
};
Action dActionPressed = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
dKey = true;
}
};
Action wActionReleased = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
wKey = false;
}
};
Action aActionReleased = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
aKey = false;
}
};
Action sActionReleased = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
sKey = false;
}
};
Action dActionReleased = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
dKey = false;
}
};
actionMap.put(W + PRESSED, wActionPressed);
actionMap.put(A + PRESSED, aActionPressed);
actionMap.put(S + PRESSED, sActionPressed);
actionMap.put(D + PRESSED, dActionPressed);
actionMap.put(W + RELEASED, wActionReleased);
actionMap.put(A + RELEASED, aActionReleased);
actionMap.put(S + RELEASED, sActionReleased);
actionMap.put(D + RELEASED, dActionReleased);
}
public void loop() {
if (wKey) yPos -= 5;
if (aKey) xPos -= 5;
if (sKey) yPos += 5;
if (dKey) xPos += 5;
repaint();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, xPos, yPos, null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ProblemExample example = new ProblemExample();
Timer timer = new Timer(60, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
example.loop();
}
});
timer.start();
}
});
}
}
答案 0 :(得分:6)
您可能认为这是MAC中的错误,而不是因为MAC具有辅助键的功能 。
因为您是MAC,我希望你知道这个功能。此功能可能是您问题的原因
使用MAC的辅助键功能:用于按住字母键将显示该字母的变体,例如按住“u”以获得“ü”。这在拼写非英语时非常方便话。
有一种简单的方法可以控制并改变长按键的行为以满足您的需求。
打开终端应用并写下:
defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool false
然后重新启动要激活此设置的任何打开的应用程序。
回复:只需将true
代替false
添加到上一个命令,如下所示:
defaults write NSGlobalDomain ApplePressAndHoldEnabled -bool true
更新:
您可以通过转到系统偏好设置,在保持键重复开始之前加快按键重复的速度或减少延迟,并在键盘标题下进行更改。
答案 1 :(得分:1)
除了Tahir Hussain Mir关于更改Mac密钥设置的建议之外,我发现问题在于循环,以事件驱动的方式实现它更有效率,我冒昧地改变你的代码有点。与Hussain Mir建议的解决方案一起,它应该可以解决您的问题。
你也可以自己处理按键重复,例如,按键启动计时器并在按键释放时停止按键,但是按键行为在Windows和Mac之间会有所不同,这不是真正的方式你想去。
$ python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime, timedelta
>>> print(datetime.now().replace(microsecond=0,second=0,minute=0)-timedelta(hours=1))
2017-01-11 16:00:00