gpt4 book ai didi

java - java中的KeyAdapter输入不起作用

转载 作者:行者123 更新时间:2023-12-01 06:07:25 28 4
gpt4 key购买 nike

我刚刚编写了一些代码来让我的玩家在我的小迷宫游戏中移动,但没有任何反应。另外,我的迷宫没有像矩阵输入那样正确绘制。我不明白为什么这段代码是错误的......任何帮助都很好。谢谢!

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import javax.swing.*;

public class Main extends JPanel {
private static Image white;
private static Image black;
private static Image finish;
private static Image player;
private static int x = 1;
private static int y = 1;
private String matrix[][];

public Main() {
addKeyListener(new Keys());
setFocusable(true);
}

public static String[][] load(String input) {
List<String[]> rows = new ArrayList<>();
try (Scanner scanner = new Scanner(input)) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
String[] cols = new String[line.length()];
for (int i = 0; i < cols.length; i++) {
cols[i] = line.substring(i, i + 1);
}
rows.add(cols);
}
}
return rows.toArray(new String[rows.size()][]);
}

public static JFrame buildFrame() {
JFrame frame = new JFrame("Labyrinth Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(900, 950);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
return frame;
}

public void moveUp() {
x += 0;
y += -1;
}

public void moveLeft() {
x += -1;
y += 0;
}

public void moveDown() {
x += 0;
y += 1;
}

public void moveRight() {
x += 1;
y += 0;
}

public class Keys extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
int keycode = e.getKeyCode();
// repaint();
if (keycode == KeyEvent.VK_W) {
if (!matrix[getX()][getY() - 1].equals("1")) {
moveUp();
}
}
if (keycode == KeyEvent.VK_A) {
if (!matrix[getX() - 1][getY()].equals("1")) {
moveLeft();
}
}
if (keycode == KeyEvent.VK_S) {
if (!matrix[getX()][getY() + 1].equals("1")) {
moveDown();
}
}
if (keycode == KeyEvent.VK_D) {
if (!matrix[getX() + 1][getY()].equals("1")) {
moveRight();
}
}
}

@Override
public void keyReleased(KeyEvent event) {
}
}

public static void main(String[] args) {
String input = "1111111111111111111111111111111111111111111\n"
+ "1000000010001000001000000010000000100000001\n"
+ "1010111010101010101111101011111010111111101\n"
+ "1010001010100010100000001010000010000010001\n"
+ "1011101010111110101111111010111111111010111\n"
+ "1000101010100000101000001000100010000010001\n"
+ "1011101011101011111011101111111010111110101\n"
+ "1010001000001010000010100000001010000010101\n"
+ "1010111111111010111110111111101011111011101\n"
+ "1010100000100010100000000000101000000000101\n"
+ "1110101111101110111110111011101011111110101\n"
+ "1000100000000010000010100010001000100010001\n"
+ "1011111111111111111011101010111111101011101\n"
+ "1000000000000000100010001010000000001010001\n"
+ "1011111111111011101110111011111111111010111\n"
+ "1000100010001000001010001000100000001010101\n"
+ "1110101011101111111010101110111110111010101\n"
+ "1000101010001000100000101000100000100010001\n"
+ "1011101010111010101111101011101110101111111\n"
+ "1000001010000010000000101000001000100010001\n"
+ "1111111011111110111111101111111011111010101\n"
+ "1000001010000010100010001000000010000010101\n"
+ "1011111010111011101010111011111110101110101\n"
+ "1010000010001010001010001000100000101010101\n"
+ "1010111111101010111011101111101111101011101\n"
+ "1000100000001010101010001000100010101000101\n"
+ "1011111011111010101010111010111010101011101\n"
+ "1010000010001000101010000010001010001000001\n"
+ "1010101110101111101011101111101011111010101\n"
+ "1010101000101000001000101000001000000010101\n"
+ "1011101011111010111110111011101111111110111\n"
+ "1000001000000010000000000010000000000010021\n"
+ "1111111111111111111111111111111111111111111\n";

String[][] matrix = load(input);

JFrame frame = buildFrame();
ImageIcon img = new ImageIcon("C:/Users/Desktop/black20.png");
black = img.getImage();
img = new ImageIcon("C:/Users/Desktop/gri20.png");
white = img.getImage();
img = new ImageIcon("C:/Users/Desktop/finish20.png");
finish = img.getImage();
img = new ImageIcon("C:/Users/Desktop/smiley20.png");
player = img.getImage();
// frame.add(new Player());
JPanel pane = new JPanel() {
@Override
public void paint(Graphics g) {
super.paint(g);
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j].equals("1")) {
g.drawImage(black, i * 20, j * 20, null);
}
if (matrix[i][j].equals("0")) {
g.drawImage(white, i * 20, j * 20, null);
}
if (matrix[i][j].equals("2")) {
g.drawImage(finish, i * 20, j * 20, null);
}
}
}
g.drawImage(player, x * 20, y * 20, null);
}
};
frame.add(pane);
frame.add(new Main());
}
}

它应该看起来像:

enter image description here

最佳答案

问题/建议:

  • 您正在以默认方式向 JFrame 添加多个组件。由于 JFrame 的 contentPane 使用 BorderLayout,因此只会显示一个组件(最后添加的一个组件),而另一个组件将被完全覆盖并保持不可见。
  • 您的主 JPanel 并未用作真正的 JPanel。没有添加任何内容,事实上它看起来应该是一个逻辑类而不是组件类。
  • 不要使用 KeyListeners,因为在焦点问题方面,KeyListeners 非常烦人,请使用 Key Bindings这将使您能够以干净且更高层次的方式解决焦点问题。
  • 不要重写 JPanel 的 Paint 方法,而应重写其 paintComponent 方法,因为这将为您带来多种优势,包括默认使用动画双缓冲。
  • 不要不小心为组件类提供 public int getX()public int getY() 方法,因为这些方法会覆盖将组件放入其容器中的关键方法。由于 Main 类甚至不应该扩展 JPanel,因此这对于您的代码来说最终不会成为问题,但在将来,它会弄乱您的程序。
  • 当您遇到类似问题(例如 KeyListener 无法工作)时,请从大程序中删除该问题,并尝试在一个小的单独程序中重现该问题。这将为您提供一个更干净的环境,帮助您隔离和理解问题,从而帮助您解决问题。
  • 您的程序错误地使用了 static 修饰符。您的 x 和 y 字段不应是静态的,也不应以静态方式访问。
  • 您的 main 方法中的代码太多,这就是您可能将 x 和 y 设为静态的原因之一,因为您被迫这样做,因为您试图在 main 中访问它们。解决方案不是使字段静态化,而是将所有代码从静态世界中取出并放入实例世界中。
<小时/>

编辑

出于某种原因,这个问题引起了我的兴趣,因此我决定如果可能的话尝试 M-V-C 或模型- View - Controller ,看看我能想出什么。因此,这里有一堆类似工作的类,从保存数据的文本文件开始。

GUI 看起来像:

enter image description here

它必须与类文件位于同一位置,因为它是作为资源获取的,并且文件名必须为“input.txt”

1111111111111111111111111111111111111111111
1000000010001000001000000010000000100000001
1010111010101010101111101011111010111111101
1010001010100010100000001010000010000010001
1011101010111110101111111010111111111010111
1000101010100000101000001000100010000010001
1011101011101011111011101111111010111110101
1010001000001010000010100000001010000010101
1010111111111010111110111111101011111011101
1010100000100010100000000000101000000000101
1110101111101110111110111011101011111110101
1000100000000010000010100010001000100010001
1011111111111111111011101010111111101011101
1000000000000000100010001010000000001010001
1011111111111011101110111011111111111010111
1000100010001000001010001000100000001010101
1110101011101111111010101110111110111010101
1000101010001000100000101000100000100010001
1011101010111010101111101011101110101111111
1000001010000010000000101000001000100010001
1111111011111110111111101111111011111010101
1000001010000010100010001000000010000010101
1011111010111011101010111011111110101110101
1010000010001010001010001000100000101010101
1010111111101010111011101111101111101011101
1000100000001010101010001000100010101000101
1011111011111010101010111010111010101011101
1010000010001000101010000010001010001000001
1010101110101111101011101111101011111010101
1010101000101000001000101000001000000010101
1011101011111010111110111011101111111110111
1000001000000010000000000010000000000010021
1111111111111111111111111111111111111111111

接下来是主程序,它创建模型、 View 和 Controller ,将它们连接在一起,然后显示 GUI:

import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

/**
* link: http://stackoverflow.com/a/41418250/522444
*
* @author Pete
*
*/
@SuppressWarnings("serial")
public class Main2 extends JPanel {
private View mainPanel;

public Main2(MatrixModel matrixModel) {
mainPanel = new View(matrixModel);
new Controller(matrixModel, mainPanel);

setLayout(new BorderLayout());
add(mainPanel, BorderLayout.CENTER);
}

private static void createAndShowGui(MatrixModel model) {
Main2 mainPanel = new Main2(model);

JFrame frame = new JFrame("Main2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) {
final MatrixModel model = MatrixUtil.getInput(MatrixUtil.PATH_TO_RSC);

SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui(model);
}
});
}
}

接下来是一个带有静态方法的实用程序类,用于将文本文件作为资源读取并将其转换为模型对象:

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class MatrixUtil {
// again this text file must be in the jar file or the code base
// at the same location as the class / java files
public static final String PATH_TO_RSC = "input.txt";

public static MatrixModel getInput(String resourcePath) {
InputStream is = MatrixUtil.class.getResourceAsStream(resourcePath);
if (is == null) {
String text = "resourcePath is not found and not loading text: " + resourcePath;
throw new IllegalArgumentException(text);
}
return getInput(is);
}

public static MatrixModel getInput(InputStream is) {
MatrixModel model = null;
try (Scanner scan = new Scanner(is)) {
List<List<MatrixPosition>> listOfLists = new ArrayList<>();
while (scan.hasNextLine()) {
String line = scan.nextLine();
if (line.trim().isEmpty()) {
continue;
}
List<MatrixPosition> list = new ArrayList<>();
for (char c : line.toCharArray()) {
list.add(MatrixPosition.getMatrixPosition(String.valueOf(c)));
}
listOfLists.add(list);
}
MatrixPosition[][] grid = new MatrixPosition[listOfLists.size()][];
for (int i = 0; i < grid.length; i++) {
List<MatrixPosition> list = listOfLists.get(i);
grid[i] = list.toArray(new MatrixPosition[] {});
}
model = new MatrixModel(grid, new SpritePosition(1, 1));
}

return model;
}

}

表示方向的基本枚举:

public enum Direction {
UP, DOWN, LEFT, RIGHT
}

另一个枚举来表示网格中的位置点,以及它是墙、走廊还是末端,以及从数字转换为 MatrixPosition 的静态方法:

public enum MatrixPosition {
WALL(1), CORRIDOR(0), END(2);

private int value;

private MatrixPosition(int value) {
this.value = value;
}

public int getValue() {
return value;
}

public static MatrixPosition getMatrixPosition(int value) {
for (MatrixPosition position : MatrixPosition.values()) {
if (value == position.getValue()) {
return position;
}
}
String text = "value of " + value;
throw new IllegalArgumentException(text);
}

public static MatrixPosition getMatrixPosition(String strValue) {
int value = -1;
try {
value = Integer.parseInt(strValue);
} catch (NumberFormatException e) {
String text = "NumberFormatException for strValue " + strValue;
throw new IllegalAccessError(text);
}
return getMatrixPosition(value);
}
}

表示 Sprite 位置的类,类似于 java.awt.Point 类,但使用行和列字段而不是 x 和 y:

public class SpritePosition {
int row;
int column;

public SpritePosition(int row, int column) {
this.row = row;
this.column = column;
}

public int getRow() {
return row;
}

public void setRow(int row) {
this.row = row;
}

public int getColumn() {
return column;
}

public void setColumn(int column) {
this.column = column;
}

public void setRowColumn(int row, int column) {
this.row = row;
this.column = column;
}

}

该模型具有属性更改支持代码,以便它可以通知任何监听它的类其状态的任何更改。 Controller 将是监听模型的类

import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;

public class MatrixModel {
public static final String SPRITE_POINT = "sprite point";
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(this);
private MatrixPosition[][] grid;
private SpritePosition spritePosition;

public MatrixModel(MatrixPosition[][] grid, SpritePosition spritePosition) {
this.grid = grid;
this.spritePosition = spritePosition;
}

public int getRows() {
return grid.length;
}

public int getColumns() {
return grid[0].length;
}

public MatrixPosition getPosition(SpritePosition p) {
return getPosition(p.row, p.column);
}

public MatrixPosition getPosition(int row, int col) {
return grid[row][col];
}

public void setSpritePoint(SpritePosition spritePosition) {
SpritePosition oldValue = this.spritePosition;
SpritePosition newValue = spritePosition;
this.spritePosition = spritePosition;
pcSupport.firePropertyChange(SPRITE_POINT, oldValue, newValue);
}

public boolean isPointValid(SpritePosition p) {
if (p.column < 0 || p.row < 0) {
return false;
}
if (p.column >= grid[0].length || p.row >= grid.length) {
return false;
}
return grid[p.row][p.column] == MatrixPosition.CORRIDOR;
}

public boolean isMoveValid(Direction direction) {
int row = spritePosition.row;
int column = spritePosition.column;
switch (direction) {
case UP:
return isPointValid(new SpritePosition(row - 1, column));
case DOWN:
return isPointValid(new SpritePosition(row + 1, column));
case LEFT:
return isPointValid(new SpritePosition(row, column - 1));
case RIGHT:
return isPointValid(new SpritePosition(row, column + 1));
default:
return false;
}
}

public void move(Direction direction) {
if (!isMoveValid(direction)) {
String text = "For move to " + direction + "spritePosition: " + spritePosition;
throw new IllegalArgumentException(text);
}
int row = spritePosition.row;
int column = spritePosition.column;
switch (direction) {
case UP:
setSpritePoint(new SpritePosition(row - 1, column));
break;
case DOWN:
setSpritePoint(new SpritePosition(row + 1, column));
break;
case LEFT:
setSpritePoint(new SpritePosition(row, column - 1));
break;
case RIGHT:
setSpritePoint(new SpritePosition(row, column + 1));
break;

default:
break;
}
}

public SpritePosition getSpritePosition() {
return spritePosition;
}

public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}

public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}

public void addPropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(name, listener);
}

public void removePropertyChangeListener(String name, PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(name, listener);
}
}

Controller 类,它在 View 上设置键绑定(bind),以便它可以监听按键,检查它们是否代表有效的移动,如果是,则告诉模型进行移动。它还向模型添加了一个监听器,以便当其状态发生变化时,它会告诉 View 移动 Sprite

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.EnumMap;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.KeyStroke;

public class Controller {
private MatrixModel model;
private View view;
private Map<Direction, KeyStroke> dirKeyMap = new EnumMap<>(Direction.class);

public Controller(MatrixModel model, View view) {
this.model = model;
this.view = view;

dirKeyMap.put(Direction.DOWN, KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0));
dirKeyMap.put(Direction.UP, KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0));
dirKeyMap.put(Direction.LEFT, KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0));
dirKeyMap.put(Direction.RIGHT, KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));

model.addPropertyChangeListener(new ModelListener());
setUpKeyBindings(view);
}

private void setUpKeyBindings(View view) {
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inputMap = view.getInputMap(condition);
ActionMap actionMap = view.getActionMap();
for (Direction dir : Direction.values()) {
KeyStroke keyStroke = dirKeyMap.get(dir);
hookUp(inputMap, actionMap, dir, keyStroke);
}
}

private void hookUp(InputMap inputMap, ActionMap actionMap, Direction dir, KeyStroke key) {
inputMap.put(key, key.toString());
actionMap.put(key.toString(), new MoveAction(dir, model));
}

public MatrixModel getModel() {
return model;
}

public View getView() {
return view;
}

class ModelListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (MatrixModel.SPRITE_POINT.equals(evt.getPropertyName())) {
SpritePosition p = model.getSpritePosition();
view.setSpritePoint(p);
}
}
}

}

@SuppressWarnings("serial")
class MoveAction extends AbstractAction {
private Direction dir;
private MatrixModel model;

public MoveAction(Direction dir, MatrixModel model) {
super(dir.toString());
this.dir = dir;
this.model = model;
}

public void actionPerformed(ActionEvent e) {
if (model.isMoveValid(dir)) {
model.move(dir);
}
}
}

最后是 View 类,它扩展了 JPanel,用于显示迷宫和 Sprite :

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class View extends JPanel {
private static final int CELL_WIDTH = 20;
private static final Color CORRIDOR_COLOR = Color.LIGHT_GRAY;
private static final Color WALL_COLOR = Color.DARK_GRAY;
private static final Color END_COLOR = Color.ORANGE;
private static final Color SPRITE_COLOR = Color.RED;
private static final int GAP = 1;
private BufferedImage gridImg = null;
private SpritePosition spritePosition;
private JPanel mainPanel = new JPanel();

public View(MatrixModel matrixModel) {
gridImg = createImg(matrixModel);
spritePosition = matrixModel.getSpritePosition();
}

public JPanel getMainPanel() {
return mainPanel;
}

@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet() || gridImg == null) {
return super.getPreferredSize();
}
int prefW = gridImg.getWidth();
int prefH = gridImg.getHeight();
return new Dimension(prefW, prefH);
}

public void setSpritePoint(SpritePosition spritePosition) {
this.spritePosition = spritePosition;
repaint();
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (gridImg != null) {
g.drawImage(gridImg, 0, 0, this);
}
g.setColor(SPRITE_COLOR);
int y = spritePosition.row * CELL_WIDTH + GAP;
int x = spritePosition.column * CELL_WIDTH + GAP;
g.fillRect(x, y, CELL_WIDTH - 2 * GAP, CELL_WIDTH - 2 * GAP);
}

private BufferedImage createImg(MatrixModel matrixModel) {
BufferedImage img = null;
if (matrixModel != null && matrixModel.getRows() > 0) {
int w = matrixModel.getColumns() * CELL_WIDTH;
int h = matrixModel.getRows() * CELL_WIDTH;
img = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
for (int row = 0; row < matrixModel.getRows(); row++) {
for (int col = 0; col < matrixModel.getColumns(); col++) {
MatrixPosition position = matrixModel.getPosition(row, col);
Color c = null;
switch (position) {
case CORRIDOR:
c = CORRIDOR_COLOR;
break;
case WALL:
c = WALL_COLOR;
break;
case END:
c = END_COLOR;
break;
}
g2.setColor(c);
int x = col * CELL_WIDTH;
int y = row * CELL_WIDTH;
g2.fillRect(x, y, CELL_WIDTH, CELL_WIDTH);
}
}
g2.dispose();
}
return img;
}

}

关于java - java中的KeyAdapter输入不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41418003/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com