KeyListener 未在 JPanel 中实例化
KeyListener not instantiated in a JPanel
我正在创建一个简单的小游戏,我需要一些帮助来找出我正在犯的错误。这个想法是将一些面板存储在主框架内的 CardLayout 中,并在需要时在它们之间切换;我创建了一个自定义 JFrame (MainFrame) 和一堆自定义 JPanel,其中一个是 GamePanel,它已附加到自定义 KeyListener (MovementListener) 以捕获关键事件并根据需要移动玩家。问题是当我切换到 GamePanel 时,keyListener 似乎没有实例化。
要清楚,做了一堆测试,结果在 addKeyListener() 方法中,"new MovementListener()" 部分为空,但我不明白为什么。
这里是MovementListener class:
package controller.listeners;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import application.core.GameController;
import entities.Player;
import movement.Direction;
public class MovementListener implements KeyListener {
private Player player;
public MovementListener() {
this.player=GameController.getInstance().getPlayer();
}
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_W:
player.move(Direction.NORTH);
player.getAnimatedSprite().startMoving();
break;
case KeyEvent.VK_A:
player.move(Direction.WEST);
player.getAnimatedSprite().startMoving();
break;
case KeyEvent.VK_S:
player.move(Direction.SOUTH);
player.getAnimatedSprite().startMoving();
break;
case KeyEvent.VK_D:
player.move(Direction.EAST);
player.getAnimatedSprite().startMoving();
break;
default:
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_W:
player.getAnimatedSprite().stopMoving();
break;
case KeyEvent.VK_A:
player.getAnimatedSprite().stopMoving();
break;
case KeyEvent.VK_S:
player.getAnimatedSprite().stopMoving();
break;
case KeyEvent.VK_D:
player.getAnimatedSprite().stopMoving();
break;
default:
break;
}
}
@Override
public void keyTyped(KeyEvent e) {}
}
游戏面板class:
package graphics.panels;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.JPanel;
import application.core.GameController;
import controller.listeners.MovementListener;
import entities.Entity;
import entities.Living;
import graphics.ConstantsCollector;
import graphics.sprites.AnimatedSprite;
import graphics.sprites.Tile;
@SuppressWarnings("serial")
public class GamePanel extends JPanel {
public static final String NAME="Game";
private static GamePanel instance=null;
private Tile grassTile;
private Entity[][] logicMap;
private GamePanel() {
super();
logicMap = GameController.getInstance().logicMap;
grassTile = new Tile(ConstantsCollector.GRASSTEXTURE);
addKeyListener(new MovementListener());
setAlignmentX(Component.CENTER_ALIGNMENT);
setVisible(true);
setFocusable(true);
requestFocusInWindow();
grabFocus();
}
@Override
public void paintComponent(Graphics g) {
drawFloorMap(g);
drawObjects(g);
drawEntities(g);
}
private void drawFloorMap(Graphics g) {
for(int i = 0; i < ConstantsCollector.MAP_SIZE; i++)
for(int j = 0; j < ConstantsCollector.MAP_SIZE; j++)
g.drawImage(grassTile.getSprite(), Tile.calculateXPosition(i), Tile.calculateYPosition(j), Tile.calculateWidth(), Tile.calculateHeight(), null);
}
private void drawObjects(Graphics g) {
for(int i = 0; i < ConstantsCollector.MAP_SIZE; i++)
for(int j = 0; j < ConstantsCollector.MAP_SIZE; j++)
if (logicMap[i][j]!=null && !(logicMap[i][j] instanceof Living))
g.drawImage(logicMap[i][j].getTile().getSprite(), logicMap[i][j].getTile().getWidth(), logicMap[i][j].getTile().getHeight(), null);
else
g.drawImage(grassTile.getSprite(), Tile.calculateXPosition(i), Tile.calculateYPosition(j), Tile.calculateWidth(), Tile.calculateHeight(), null);
}
private void drawEntities(Graphics g) {
for(int i = 0; i < ConstantsCollector.MAP_SIZE; i++)
for(int j = 0; j < ConstantsCollector.MAP_SIZE; j++)
if (logicMap[i][j]!=null && (logicMap[i][j] instanceof Living))
{
AnimatedSprite sprite=((Living)logicMap[i][j]).getAnimatedSprite();
g.drawImage(sprite.getCurrentImage(), sprite.getWidht(), sprite.getHeight(), null);
}
}
public void update() {
repaint();
}
public static GamePanel getInstance() {
if (instance==null)
instance=new GamePanel();
return instance;
}
}
KeyListener 在 JPanel 上不起作用,请使用 registerKeyboardAction 方法。我最好这样做
class Movement {
Player player;
public void move(Direction direction) {
player.move(direction);
player.getAnimatedSprite().startMoving();
}
}
class GamePanel extends JPanel {
Movement movement = new Movement();
private GamePanel() {
KeyStroke keystroke = KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false);
registerKeyboardAction(movementListener(Direction.NORTH), keystroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
// register other key strokes
}
ActionListener movementListener(final Direction direction) {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
movement.move(direction);
}
}
}
}
ActionListener 可以在java8
中简化为 lambda
我正在创建一个简单的小游戏,我需要一些帮助来找出我正在犯的错误。这个想法是将一些面板存储在主框架内的 CardLayout 中,并在需要时在它们之间切换;我创建了一个自定义 JFrame (MainFrame) 和一堆自定义 JPanel,其中一个是 GamePanel,它已附加到自定义 KeyListener (MovementListener) 以捕获关键事件并根据需要移动玩家。问题是当我切换到 GamePanel 时,keyListener 似乎没有实例化。 要清楚,做了一堆测试,结果在 addKeyListener() 方法中,"new MovementListener()" 部分为空,但我不明白为什么。
这里是MovementListener class:
package controller.listeners;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import application.core.GameController;
import entities.Player;
import movement.Direction;
public class MovementListener implements KeyListener {
private Player player;
public MovementListener() {
this.player=GameController.getInstance().getPlayer();
}
@Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_W:
player.move(Direction.NORTH);
player.getAnimatedSprite().startMoving();
break;
case KeyEvent.VK_A:
player.move(Direction.WEST);
player.getAnimatedSprite().startMoving();
break;
case KeyEvent.VK_S:
player.move(Direction.SOUTH);
player.getAnimatedSprite().startMoving();
break;
case KeyEvent.VK_D:
player.move(Direction.EAST);
player.getAnimatedSprite().startMoving();
break;
default:
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
switch (e.getKeyCode()) {
case KeyEvent.VK_W:
player.getAnimatedSprite().stopMoving();
break;
case KeyEvent.VK_A:
player.getAnimatedSprite().stopMoving();
break;
case KeyEvent.VK_S:
player.getAnimatedSprite().stopMoving();
break;
case KeyEvent.VK_D:
player.getAnimatedSprite().stopMoving();
break;
default:
break;
}
}
@Override
public void keyTyped(KeyEvent e) {}
}
游戏面板class:
package graphics.panels;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.JPanel;
import application.core.GameController;
import controller.listeners.MovementListener;
import entities.Entity;
import entities.Living;
import graphics.ConstantsCollector;
import graphics.sprites.AnimatedSprite;
import graphics.sprites.Tile;
@SuppressWarnings("serial")
public class GamePanel extends JPanel {
public static final String NAME="Game";
private static GamePanel instance=null;
private Tile grassTile;
private Entity[][] logicMap;
private GamePanel() {
super();
logicMap = GameController.getInstance().logicMap;
grassTile = new Tile(ConstantsCollector.GRASSTEXTURE);
addKeyListener(new MovementListener());
setAlignmentX(Component.CENTER_ALIGNMENT);
setVisible(true);
setFocusable(true);
requestFocusInWindow();
grabFocus();
}
@Override
public void paintComponent(Graphics g) {
drawFloorMap(g);
drawObjects(g);
drawEntities(g);
}
private void drawFloorMap(Graphics g) {
for(int i = 0; i < ConstantsCollector.MAP_SIZE; i++)
for(int j = 0; j < ConstantsCollector.MAP_SIZE; j++)
g.drawImage(grassTile.getSprite(), Tile.calculateXPosition(i), Tile.calculateYPosition(j), Tile.calculateWidth(), Tile.calculateHeight(), null);
}
private void drawObjects(Graphics g) {
for(int i = 0; i < ConstantsCollector.MAP_SIZE; i++)
for(int j = 0; j < ConstantsCollector.MAP_SIZE; j++)
if (logicMap[i][j]!=null && !(logicMap[i][j] instanceof Living))
g.drawImage(logicMap[i][j].getTile().getSprite(), logicMap[i][j].getTile().getWidth(), logicMap[i][j].getTile().getHeight(), null);
else
g.drawImage(grassTile.getSprite(), Tile.calculateXPosition(i), Tile.calculateYPosition(j), Tile.calculateWidth(), Tile.calculateHeight(), null);
}
private void drawEntities(Graphics g) {
for(int i = 0; i < ConstantsCollector.MAP_SIZE; i++)
for(int j = 0; j < ConstantsCollector.MAP_SIZE; j++)
if (logicMap[i][j]!=null && (logicMap[i][j] instanceof Living))
{
AnimatedSprite sprite=((Living)logicMap[i][j]).getAnimatedSprite();
g.drawImage(sprite.getCurrentImage(), sprite.getWidht(), sprite.getHeight(), null);
}
}
public void update() {
repaint();
}
public static GamePanel getInstance() {
if (instance==null)
instance=new GamePanel();
return instance;
}
}
KeyListener 在 JPanel 上不起作用,请使用 registerKeyboardAction 方法。我最好这样做
class Movement {
Player player;
public void move(Direction direction) {
player.move(direction);
player.getAnimatedSprite().startMoving();
}
}
class GamePanel extends JPanel {
Movement movement = new Movement();
private GamePanel() {
KeyStroke keystroke = KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false);
registerKeyboardAction(movementListener(Direction.NORTH), keystroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
// register other key strokes
}
ActionListener movementListener(final Direction direction) {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
movement.move(direction);
}
}
}
}
ActionListener 可以在java8
中简化为 lambda