KeyListener无法正常工作(requestFocus没有修复它)

我试图在没有youtubevideo帮助的情况下制作我的第一个游戏。 我看过很多关于制作java游戏的youtube系列,他们从来没有我想做的事情,所以经过充分的学习,我开始制作自己的游戏。 我知道足够的Java可以绕过,到目前为止一切都没有问题。

我试过寻求一些帮助,但我能找到人们说尝试的东西:

setFocusable(true); requestFocus(); 

然而,这对我没有用。 我知道大多数人不想只查看我的所有代码,但我认为它是可管理的(它还没有那么多代码)。

我打算把它变成一种类似蛇的游戏,你变得更大而不是更长,而你是一只豚鼠(现在用橙色矩形代表)而不是蛇。

Game.java:

 package com.kaperly.game; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.io.IOException; import javax.swing.JFrame; import javax.swing.JPanel; public class Game extends JFrame { private static final long serialVersionUID = 1L; public static JFrame frame; public static JPanel panel; public static int width = 1000; public static int height = 600; public Game() { frame = new JFrame(); panel = new Panel(); frame.setPreferredSize(new Dimension(width, height)); frame.setResizable(false); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setTitle("Guinea Pig Eat"); frame.setLayout(new BorderLayout()); frame.setVisible(true); panel.setFocusable(true); panel.requestFocus(true); frame.add(panel, BorderLayout.CENTER); frame.pack(); } public static void init() { } public static void loop() throws InterruptedException { while(true) { Character.move(); Thread.sleep(10); }} public static void main(String[] args) throws InterruptedException, IOException { Game game = new Game(); init(); loop(); } } 

Panel.java:

 package com.kaperly.game; import java.awt.Color; import java.awt.Graphics; import java.awt.Image; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.JPanel; public class Panel extends JPanel implements KeyListener { private static final long serialVersionUID = 1L; public static Image startButton; public static boolean goingRight = false; public static boolean goingLeft = false; public static boolean goingUp = false; public static boolean goingDown = false; private static int changeDirection = 0; @Override public void keyPressed(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_W) { goingUp = true; changeDirection = 1; System.out.println("Moved Up!"); }else if(e.getKeyCode() == KeyEvent.VK_A) { goingLeft = true; changeDirection = 2; }else if(e.getKeyCode() == KeyEvent.VK_S) { goingDown = true; changeDirection = 3; }else if(e.getKeyCode() == KeyEvent.VK_D) { goingRight = true; changeDirection = 4; }else if(changeDirection == (1 | 2 | 3 | 4)) { changeDirection = 0; if(changeDirection == 1) { goingLeft = false; goingDown = false; goingRight = false; }else if(changeDirection == 2) { goingUp = false; goingDown = false; goingRight = false; }else if(changeDirection == 3) { goingUp = false; goingLeft = false; goingRight = false; }else if(changeDirection == 4) { goingUp = false; goingLeft = false; goingDown = false; } } } @Override public void keyReleased(KeyEvent e) { } @Override public void keyTyped(KeyEvent e) { } public void paintComponent(Graphics g) { super.paintComponent(g); //Set background color g.setColor(Color.GRAY); g.fillRect(0, 0, Game.width, Game.height); //Make Walls g.setColor(Color.BLACK); g.fillRect(0, 0, Game.width, 25); g.fillRect(0, 550, Game.width, 25); g.fillRect(0, 0, 25, Game.height); g.fillRect(970, 0, 25, Game.height); //Show Character g.setColor(Color.ORANGE); g.fillRect(Character.x, Character.y, Character.width, Character.height); repaint(); } } 

Character.java:

 package com.kaperly.game; public class Character { public static int x = 475; public static int y = 250; public static int width = 50; public static int height = 75; public static void move() { if(Panel.goingUp == true) { y = y ++; } if(Panel.goingLeft == true) { x = x --; } if(Panel.goingDown == true) { y = y --; } if(Panel.goingRight == true) { x = x ++; } } } 

应该避免使用KeyListener ,因为它固有的焦点相关问题。 你永远不知道什么可能会使键盘焦点远离你的组件。

相反,利用Key Bindings API,它允许您控制触发键事件所需的焦点级别。

它还允许您重用与其他地方的键绑定相关联的基础Action

你最好将类Panel重命名为更有意义的东西。 AWT已经有了一个Panel类,很容易让两者混淆

KeyListener有两个大问题,它们被绑定为所有键,除了组件必须可聚焦和焦点, JPanel默认情况下不可聚焦。

api强烈建议使用requestFocus

而不是你可以使用KeyBindings绑定特定键的动作。

您可能对@camickr博客感兴趣,在那里他使用键盘发布了类似Motion的 swing utils。

也不要调用类Panel导致它的JPanel父类名,这给混乱带来了麻烦。

改变这个:

 public class Game extends JFrame { private JFrame frame; } 

 public class Game { private JFrame frame; } 

另一件事是没有在顶级类实现KeyListener ,而是使用anonymous classesprivate classes来破坏单一责任原则

您需要在游戏或面板类上注册keylistener。 文档有这样的说法:

然后,使用组件的addKeyListener方法向该组件注册从该类创建的侦听器对象。 按下,释放或键入键时会生成键盘事件。 然后调用侦听器对象中的相关方法,并将KeyEvent传递给它。

所以在Panel中你可以做到以下几点

  public Panel(){ addKeyListener(this); } 

您的代码还有其他问题,但这应该有输入工作。