如何在Java中正确使用KeyListener

3
我正在尝试使用KeyListner来通过左右键向前和向后移动此游戏中的角色,但我似乎无法移动角色。我查看了以下答案,但没有成功:

如何在Java中正确使用KeyListener如何在Java中使用KeyListener?

这是我的代码:

package test2;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test
{
    public static void main(String[] args)
    {
        Frame A1 = new Frame();
    }

}

class Frame
{
    JFrame window;

    public Frame ()
    {
        awt();
    }

    public void awt()
    {
        Design A2 = new Design()
        {
            @Override
            public void keyTyped(KeyEvent e)
            {
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }

            @Override
            public void keyPressed(KeyEvent e)
            {
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }

            @Override
            public void keyReleased(KeyEvent e)
            {
                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
            }
        };

        window = new JFrame("Kyo's test");

        window.setVisible(true);
        window.setSize(1280, 786);
        window.add(A2);

        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}


abstract class Design extends JPanel implements ActionListener, KeyListener
{
    // Timer objects for character and saws
    Timer movementOfCharacter = new Timer(5, this);
    Timer movementOfSaw = new Timer(15, this);

    // Variables for movement
    int xAxisOfCharacter = 50, velocityOfCharacter=2, yAxisOfSaw = 0, velocityOfSaw = 10;

    private Image tree, background, character, saw;


    // Constructor
    Design()
    {
        movementOfCharacter.start();

        addKeyListener(this);

        setFocusable(true);
        setFocusTraversalKeysEnabled(false);
    }

    // Constructor of Graphics
    protected void paintComponent(Graphics graphics)
    {
        super.paintComponent(graphics);

        Graphics2D graphics2d = (Graphics2D) graphics;

        graphics2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        movementOfSaw.start();

        // Body for background
        {
            ImageIcon whale = new ImageIcon(this.getClass().getResource("whale.jpg"));
            background = whale.getImage();

            graphics2d.drawImage(background, 0, 0, getWidth(), getHeight(), this);
        }

        // Body for trees
        {
            ImageIcon environment = new ImageIcon(this.getClass().getResource("Tree_Alt.png"));
            tree = environment.getImage();

            graphics2d.drawImage(tree, getWidth()/8, getHeight()-217, this);
            graphics2d.drawImage(tree, (getWidth()/5)*2, getHeight()-217, this);
            graphics2d.drawImage(tree, (getWidth()/6)*4, getHeight()-217, this);
        }

        // Body for Saws of death
        {
            ImageIcon sawOfDeath = new ImageIcon(this.getClass().getResource("saw.gif"));
            saw = sawOfDeath.getImage();

            // First saw
            {
                graphics2d.drawImage(saw, (getWidth()/11), yAxisOfSaw, 100, 100, this);
            }

            // Second saw
            {
                graphics2d.drawImage(saw, (getWidth()/7)*2, yAxisOfSaw, 100, 100, this);
            }

            // Thirf saw
            {
                graphics2d.drawImage(saw, (getWidth()/2)-10, yAxisOfSaw, 100, 100, this);
            }

            // Fourth saw
            {
                graphics2d.drawImage(saw, (getWidth()/6)*4, yAxisOfSaw, 100, 100, this);
            }

            // Fifth saw
            {
                graphics2d.drawImage(saw, (getWidth()/6)*5, yAxisOfSaw, 100, 100, this);
            }
        }

        // Body for exit
        {
            graphics.setColor(Color.red);
            graphics.fillRect(getWidth()-5, getHeight()-150, 5, 150);
        }

        // Body for Character
        {
            ImageIcon blanka = new ImageIcon(this.getClass().getResource("Blank.gif"));
            character = blanka.getImage();

            graphics2d.drawImage(character, xAxisOfCharacter, getHeight()-150, 150, 155, this);
        }
    }

    public void actionPerformed(ActionEvent e)
    {
        yAxisOfSaw += velocityOfSaw;

        if(yAxisOfSaw > 0 || yAxisOfSaw < getHeight()-100)
            velocityOfSaw = -velocityOfSaw;

        repaint();
    }

    public void keyPressed(KeyEvent e)
    {
        int key = e.getKeyCode();

        if(key == KeyEvent.VK_LEFT)
        {
            velocityOfCharacter = -5;
        }
        if(key == KeyEvent.VK_RIGHT)
        {
            velocityOfCharacter = 5;
        }
    }

    public void keyTyped(KeyEvent e)
    {
    }

    public void keyReleased(KeyEvent e)
    {
    }
}

请问有人可以告诉我在哪里出了问题,做错了什么吗?

你好,欢迎来到StackOverflow。请花些时间阅读帮助页面,特别是名为“我可以在这里问什么话题?”和“我应该避免提出哪些类型的问题?”的部分。更重要的是,请阅读Stack Overflow问题清单。你可能还想了解最小化、完整化和可验证示例 - Clijsters
不直接涉及您的问题,但是:绘画方法仅用于绘画。每次执行repaint()或Swing确定需要绘制组件时,都会调用此方法。因此:1)不要反复开始计时器。 2)不要反复读取图像文件。这将减慢游戏速度。所有图像都应在构造函数中读取。 3)所有{....}块都是怎么回事。您不需要为注释添加一段代码块。 - camickr
1个回答

1
问题

当您执行

Design A2 = new Design() {
    @Override
    public void keyTyped(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
     public void keyPressed(KeyEvent e) {
         throw new UnsupportedOperationException("Not supported yet."); 
    }

    @Override
    public void keyReleased(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
};

您正在用仅抛出异常的方式覆盖您在Design抽象类中编写的代码。
解决方案
您的Design类不必是abstract,因为它没有未实现的方法。因此,我可以看到两种使用您在Design类中编写的代码的方法:
第一种方法
删除abstract关键字,这样您就可以像普通类一样使用new关键字实例化Design类。因此,请以以下方式声明Design类:
class Design extends JPanel implements ActionListener, KeyListener

然后以这种方式实例化A2:
Design A2 = new Design();

第二种方式

如果出于某种原因,您需要将类设置为抽象类,则可以按照以下方式实例化A2对象:

Design A2 = new Design() {};

这样做可以使代码正常运行而不会覆盖你在Design类中编写的任何方法。但是这种方式很少使用,上述第一种方式更加合理。

注释

注释1

现在,如果你在Design.keyPressed中添加一个打印输出,你会发现它被调用了(你将在控制台看到日志):

public void keyPressed(KeyEvent e) {
    System.out.println("KeyEvent: "+e);
    int key = e.getKeyCode();
    ...

注意2

另外看看keyPressed方法,我认为您还需要更新字符的X轴坐标,所以在if语句后面添加这行代码:

xAxisOfCharacter += velocityOfCharacter;

它应该像这样:
public void keyPressed(KeyEvent e) {
    System.out.println("KeyEvent: "+e);
    int key = e.getKeyCode();

    if(key == KeyEvent.VK_LEFT) {
        velocityOfCharacter = -5;
    }
    else if(key == KeyEvent.VK_RIGHT) {
        velocityOfCharacter = 5;
    }
    xAxisOfCharacter += velocityOfCharacter;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接