首页 > 解决方案 > KeyListener 和 ActionListener 未注册

问题描述

我一直在从事一个 Java 项目,该项目使角色随键移动,但 keyListener 无法正常工作并注册我的操作。我在 Eclipse 中编码,我认为问题出在我的 GamePanel、Player 或我的 KeyChecker 类上。我正在使用指南来帮助启动它,因此它与另一个项目的代码相同,但它不起作用。这是我的代码:

类平台游戏:

import java.awt.Dimension;
import java.awt.Toolkit;
import javax.swing.JFrame;

public class Platformer {

    public static void main(String[] args) {
    
        MainFrame frame = new MainFrame();
        frame.setSize(700,700);
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setTitle("Platformer");
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

class GamePanel:如果那是原始问题,我尝试更改 if 语句的布局,但它没有改变任何东西。我还尝试将语句更改为 justvoid而不是,public void但这也不起作用。

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;

public class GamePanel extends JPanel implements ActionListener{

    Player player;
    ArrayList<Wall> walls = new ArrayList<>();
    Timer gameTimer;
    
    public GamePanel() {
        
        player = new Player(400, 300, this);
        
        makeWalls();
        
        gameTimer = new Timer();
        gameTimer.schedule(new TimerTask() {

            public void run() {
                player.set();
                repaint();  
            }
            
        },0,17);
    }

    public void makeWalls() {
        for (int i = 50; i < 650; i += 50) {
            walls.add (new Wall(i, 600, 50, 50));
        }
        walls.add(new Wall(50, 550, 50, 50));
        walls.add(new Wall(50, 500, 50, 50));
        walls.add(new Wall(50, 450, 50, 50));
        walls.add(new Wall(600, 550, 50, 50));
        walls.add(new Wall(600, 500, 50, 50));
        walls.add(new Wall(600, 450, 50, 50));
        walls.add(new Wall(450, 550, 50, 50));

    }
    
    public void paint(Graphics g) {
        
        super.paint(g);
        Graphics2D gtd = (Graphics2D) g;
        player.draw(gtd);
        for (Wall wall: walls) wall.draw(gtd);
    }
    
    public void KeyPressed(KeyEvent e) {
        if (e.getKeyChar() == 'a')player.keyLeft = true;
        if (e.getKeyChar() == 'w') player.keyUp = true;
        if (e.getKeyChar() == 's') player.keyDown = true;
        if (e.getKeyChar() == 'd') player.keyRight = true;
    }
    
    public void KeyReleased(KeyEvent e) {
        if (e.getKeyChar() == 'a') player.keyLeft = false;
        if (e.getKeyChar() == 'w') player.keyUp = false;
        if (e.getKeyChar() == 's') player.keyDown = false;
        if (e.getKeyChar() == 'd') player.keyRight = false;
    }
    
    public void actionPerformed(ActionEvent e) {
    }
    
}

class Player:我也尝试了与 GamePanel 相同的方法,但也没有用。

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;

public class Player {
    
    GamePanel panel;
    int x;
    int y;
    int width;
    int height;
    
    double xspeed;
    double yspeed;
    
    Rectangle hitBox;
    
    boolean keyRight;
    boolean keyLeft;
    boolean keyUp;
    boolean keyDown;
    
    public Player(int x, int y, GamePanel panel) {
        
        this.panel = panel;
        
        this.x = x;
        this.y = y;
        
        width = 50;
        height = 100;
        hitBox = new Rectangle(x,y,width,height);
    }
    
    public void set() {
    
        if (keyLeft && keyRight || !keyLeft && !keyRight) xspeed *= 0.8;
        else if (keyLeft && !keyRight) xspeed --;
        else if (keyRight && !keyLeft) xspeed ++;
        
        if (xspeed > 0 && xspeed < 0.75) xspeed = 0;
        if (xspeed < 0 && xspeed > - 0.75) xspeed = 0;
        
        if (xspeed > 7) xspeed = 7;
        if (xspeed < -7) xspeed = -7;
        
        if (keyUp) {
            
            hitBox.y++;
            for(Wall wall: panel.walls) {
                if (wall.hitBox.intersects(hitBox)) yspeed = -6;
            }
            hitBox.y --;            
        }
        
        yspeed += .3;
        
        hitBox.x += xspeed;
        for(Wall wall: panel.walls) {
            if (hitBox.intersects(wall.hitBox)) {
                hitBox.x-= xspeed;
                while(!wall.hitBox.intersects(hitBox)) hitBox.x += Math.signum(xspeed);
                hitBox.x -= Math.signum(xspeed);
                xspeed = 0;
                x = hitBox.x;
            }
        }
        
        hitBox.y += xspeed;
        for(Wall wall: panel.walls) {
            if (hitBox.intersects(wall.hitBox)) {
                hitBox.y-= yspeed;
                while(!wall.hitBox.intersects(hitBox)) hitBox.y += Math.signum(yspeed);
                hitBox.y -= Math.signum(yspeed);
                yspeed = 0;
                y = hitBox.y;
            }
        }
        
        x += xspeed;
        y += yspeed;
        
        hitBox.x = x;
        hitBox.y = y;       
    }
    
    public void draw(Graphics2D gtd) {
        gtd.setColor(Color.BLACK);
        gtd.fillRect(x, y, width, height);
        
    }   
}

类 KeyChecker:

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class KeyChecker extends KeyAdapter{
    
    GamePanel panel;
    
    public KeyChecker(GamePanel panel) {
        this.panel = panel;
    }
    
    public void KeyPressed(KeyEvent e) {
        panel.KeyPressed(e);
    }
    
    public void KeyReleased(KeyEvent e) {
        panel.KeyReleased (e);
    }
}

类墙:

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;

public class Wall {
    int x;
    int y;
    int width;
    int height;
    
    Rectangle hitBox;
    
    public Wall (int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = width;
        
        hitBox = new Rectangle(x, y, width, height);
    }
    
    public void draw(Graphics2D gtd) {
        gtd.setColor(Color.BLACK);
        gtd.drawRect(x, y, width, height);
        gtd.setColor(Color.WHITE);
        gtd.fillRect(x + 1, y + 1, width - 2, height - 2);
    }
}

主框架类:

import java.awt.Color;
import javax.swing.JFrame;

public class MainFrame extends JFrame{
    
    public MainFrame() {
        
        GamePanel panel = new GamePanel();
    
        panel.setLocation(0,0);
        panel.setSize(this.getSize());
        panel.setBackground(Color.LIGHT_GRAY);
        panel.setVisible(true);
        this.add(panel);
        
        addKeyListener(new KeyChecker(panel));
    }
}

感谢您的帮助。

标签: javaswingjpanelactionlistenerkeylistener

解决方案


KeyChecker 中的函数应该以小写开头,因此 public void keyPressed 和 keyReleased。此外,您应该添加implements KeyListenerKeyChecker 和 GamePanel 类(移除 GamePanel 中的 ActionListener)。然后,添加未实现的函数。Eclipse 会要求您提供它。

@Override
public void keyPressed(KeyEvent e) {
    // TODO Auto-generated method stub
    
}

@Override
public void keyReleased(KeyEvent e) {
    // TODO Auto-generated method stub
    
}

备注,最好 @Override 函数 keyPressed 和 keyReleased,而不是创建新函数。

我试过了,它奏效了!


推荐阅读