【问题标题】:KeyListener not responding in JFrameKeyListener 在 JFrame 中没有响应
【发布时间】:2016-06-06 05:33:37
【问题描述】:

我为非常简单的 pong 编写了这段代码,一切正常,只是我不知道如何使 KeyListener 工作。我不知道在哪里放置 Listener 或如何使用它。欢迎任何其他提示,我是菜鸟,所以请解释到那个级别。

package pong;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class Pong extends JPanel implements KeyListener
{   
    int border = 15;

    int enemyScore = 0;
    int playerScore = 0;

    int ballx = 248;
    int bally = 170;

    int playerx = 482;
    double playery = 162;
    int playeryy = 162;

    int enemyx = 0;
    double enemyy = 162;
    int enemyyy = 162;

    boolean gameReset = true;

    boolean down;
    boolean right;

    //ball movement
    private void moveBall()
    {
        Random rand = new Random();

        while (gameReset == true)
        {
            ballx = 240;
            bally = 170;
            down = rand.nextBoolean();
            right = rand.nextBoolean();
            gameReset = false;
        }

        if (right == true)
        {
            ballx++;
        }
        else
        {
            ballx--;
        }

        if (down == true)
        {
            bally++;
        }
        else
        {
            bally--;
        }

        if(bally == getHeight()-border)
        {
            down = false;
        }
        else if (bally == 0)
        {
            down = true;
        }

        if (playeryy < bally+14 && playeryy+59 > bally && ballx == 468)
        {
            right = false;
        } 
        else if (ballx == getWidth()-border)
        {
            gameReset = true;
            enemyScore ++;
        }
        else if (enemyyy < bally+14 && enemyyy+59 > bally && ballx == 13)
        {
            right = true;
        } 
        else if (ballx == 0)
        {
            gameReset = true;
            playerScore ++;
        }
    }


    //enemy movement
    private void moveEnemy()
    {
        if (right == false && bally > enemyy+8 && enemyy < 294)
        {
            enemyy += 0.8;
            enemyyy = (int) enemyy;
        }
        else if (right == false && bally < enemyy+8 && enemyy > 0)
        {
            enemyy -= 0.8;
            enemyyy = (int) enemyy;
        }
    }

    //Drawing
    @Override                               
    public void paint(Graphics g)
    {
        super.paint(g);
        g.fillRect(enemyx, enemyyy, 15, 60);
        g.fillRect(playerx, playeryy, 15, 60);
        g.fill3DRect(ballx, bally, 15, 15, true);
        System.out.println("Enemy Score: " + enemyScore + " Player Score: "+ playerScore);
    }

    public static void main(String[] args) throws InterruptedException
    {

        JFrame frame = new JFrame("p0ng");                      //makes new frame
        frame.setSize(512,384);                                 //sets the size
        frame.setVisible(true);                                 //makes it visble
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   //allows it to sleep
        Pong game = new Pong();
        frame.add(game);

        while(true)
        {
            game.moveBall();
            game.moveEnemy();
            game.repaint();

            Thread.sleep(10);
        }     
    }  

    @Override
    public void keyTyped(KeyEvent ke) {
        //not being used
    }

    //Player movement
     @Override
    public void keyPressed(KeyEvent e) 
    {  
        if (e.getKeyCode() == KeyEvent.VK_UP && playery < 294)
        {
            playery += .8;
            playeryy = (int) playery;
        }
            else if (e.getKeyCode() == KeyEvent.VK_DOWN && playery > 0)
        {
            playery -= .8;
            playeryy = (int) playery;
        }
        repaint();
    }

    @Override
    public void keyReleased(KeyEvent ke) {
        //not being used
    }
}

【问题讨论】:

  • 你将 keylistener 添加到你的框架中
  • 在哪里添加?
  • 你可以使用 Frame.addKeyListener(game)
  • 当提供的答案“有时”有效时,看看如何使用How to Use Key Bindings正确修复它们

标签: java jframe keylistener


【解决方案1】:

欢迎任何其他提示

  • 不要使用KeyListener,它太不可靠了,尤其是当有更好的选择时。首先看看How to Use Key Bindings
  • 一般来说,您应该覆盖paintComponent 而不是paint。看看Performing Custom PaintingPainting in AWT and Swing
  • 您违反了 Swing 的单线程规则,并冒着核心逻辑和 UI 之间竞争条件的风险。查看Concurrency in Swing 了解更多详情,查看How to use Swing Timers 了解简单解决方案
  • 您的“主”循环设置错误。循环的每次迭代都应该更新需要绘制的当前状态。您不应该使用“保持”循环来“暂停”状态,而应使用 if 语句根据当前状态阻止您需要/不需要执行的部分

【讨论】:

  • 你能告诉我用这段代码会是什么样子吗?我很难理解如何使用键绑定
【解决方案2】:
public Pong(){
addKeyListner(this);
}

您需要将您的panel 注册到keyListner。 您可以使用 addKeyListner 方法来执行此操作,因为您已将 Keylistner 实现为相同的 class 。您可以使用this 关键字。您可以在constructor 中执行此操作。

【讨论】:

  • “这是一个错误的答案。” - 这个也是。虽然它“可能”有效,但它并不可靠,一般来说,KeyListener 是一个糟糕的选择,尤其是当存在更可靠的解决方案时
  • 我不知道你为什么说KeyListener 是一个糟糕的选择你能告诉我为什么吗?
  • KeyListener 是一个糟糕的选择,因为它不可靠。它只会在它注册的组件是可聚焦的并且有焦点时触发事件,因为 OP 的代码不满足这些约束,它将继续无法工作。即使它们确实使组件具有焦点并且能够使组件集中,也不需要太多的焦点就可以改变焦点,整个事情又会再次中断
  • 好吧 jPanel 默认是 isFocusable ,但使用 KeyBindings 而不是 key listner 是一个不错的选择。这个链接stackoverflow.com/questions/15290035/… 解释了为什么我们应该使用 KeyBindings。感谢@MadProgrammer 真的很有帮助
猜你喜欢
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多