至少有3个问题:
>使用KeyListener. KeyListener是众所周知的,它仅响应可聚焦且具有键盘焦点的组件上发生的键事件.默认情况下,JPanel不能聚焦,因此无法接收键盘焦点.更好的解决方案是使用键绑定API,该API可以定义触发绑定之前组件必须具有的焦点级别,并允许您将Action重用于多个键,从而减少代码重复
>覆盖油漆.强烈建议在执行自定义绘画时重写paintComponent而不是paint.您还没有维护油漆链,这将不会导致任何奇怪而奇妙的油漆伪影. Painting in AWT and Swing和Performing Custom Painting了解更多详细信息
>使用空布局.避免使用空布局,像素完美布局是现代ui设计中的一种幻觉.有太多因素会影响组件的单个大小,您无法控制. Swing旨在与布局经理为核心一起工作,舍弃这些问题不会导致问题和问题的终结,您将花费越来越多的时间来尝试纠正
例如…
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private int xPos;
public TestPane() {
Action leftAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
xPos -= 2;
if (xPos < 0) {
xPos = 0;
}
repaint();
}
};
Action rightAction = new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
xPos += 2;
if (xPos + 10 > getWidth()) {
xPos = getWidth() - 10;
}
repaint();
}
};
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), leftAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_KP_LEFT, 0), leftAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_4, 0), leftAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.left", KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), leftAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), rightAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_KP_RIGHT, 0), rightAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_6, 0), rightAction);
bindKeyStroke(WHEN_IN_FOCUSED_WINDOW, "move.right", KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), rightAction);
}
protected void bindKeyStroke(int condition, String name, KeyStroke keyStroke, Action action) {
InputMap im = getInputMap(condition);
ActionMap am = getActionMap();
im.put(keyStroke, name);
am.put(name, action);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
int yPos = (getHeight() - 10) / 2;
g2d.drawRect(xPos, yPos, 10, 10);
g2d.dispose();
}
}
}