如何在java中正确使用keylistener

Posted

技术标签:

【中文标题】如何在java中正确使用keylistener【英文标题】:How to properly use keylistener in java 【发布时间】:2018-09-25 22:15:03 【问题描述】:

我正在尝试使用KeyListner 使用左右键来前后移动游戏中的角色,但我似乎无法稍微移动角色。我看着这个答案没有运气:

How to use keyListener properly in Java 和 How do i use KeyListener in java?

这是我的代码:

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)
    
    

谁能告诉我我在哪里做错了什么?

【问题讨论】:

您好,欢迎来到 ***。请花一些时间阅读帮助页面,尤其是名为"What topics can I ask about here?" 和"What types of questions should I avoid asking?" 的部分。更重要的是,请阅读the Stack Overflow question checklist。您可能还想了解Minimal, Complete, and Verifiable Examples。 与您的问题没有直接关系,但是:绘画方法仅用于绘画。每次执行 repaint() 或 Swing 确定需要绘制组件时,都会调用此方法。因此: 1) 不要一直启动定时器。 2)不要继续阅读图像文件。这会减慢游戏速度。所有图像都应在构造函数中读取。 3)所有的 .... 块是什么。您无需为注释添加代码块。 【参考方案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,因为它没有未实现的方法。所以我可以看到 2 种方法来使用你在 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;

【讨论】:

以上是关于如何在java中正确使用keylistener的主要内容,如果未能解决你的问题,请参考以下文章

HMAC-SHA1:如何在 Java 中正确执行?

如何在 Java 中正确执行线程回调?

如何在Java中正确使用printf格式化

如何在 Java 中正确创建线程安全的单例工厂? [复制]

在用户在java中输入正确的输入之前,如何从用户那里获得输入?

Java如何检查日期格式是否正确?