2 c j33 C_J33 于 2016.03.12 21:19 提问

求救。为什么键盘监听事件不响应了。。

mport java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;

public class GamePanel extends JPanel implements ActionListener {
public static final int B_WIDTH = 450;
public static final int B_HEIGHT = 450;
public static final int DOT_SIZE = 15;
public static final int ALL_DOTS = 900;
public static final int DELAY = 100;
private static final Font gameOverFont = new Font("Verdana", Font.BOLD, 60);

public boolean inGame = true;
public String playerName;
public Timer timer;
boolean live = true;
JFrame myJFrame = null;
Image offScreenImage = null;
Snake mySnake = new Snake();
Food f = new Food();

public static void main(String[] args) {
    new GamePanel().launchGame();
}

public void launchGame() {
    myJFrame = new JFrame();
    myJFrame.setTitle("Snake");
    myJFrame.setLocation(400,200);
    myJFrame.setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
    myJFrame.setContentPane(new WelcomePanel(this));
    myJFrame.addKeyListener(new GamePanel().new KeyMonitor());
    myJFrame.pack();
    myJFrame.setVisible(true);
    myJFrame.setResizable(false);
    myJFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    myJFrame.addWindowListener(new WindowAdapter() {

        @Override
        public void windowClosing(WindowEvent e) {
            timer.stop();
            int exit = JOptionPane.showConfirmDialog(null, "确定退出吗", "友情提示", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
            if(exit == JOptionPane.YES_OPTION) {
                System.exit(0);
            } else {
                timer.start();
                return;
            }
        }

    });

    timer = new Timer(DELAY, this);
}

public GamePanel() {
    this.setBackground(Color.BLACK);
    this.setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
    this.setFocusable(true);
    this.addKeyListener(new KeyMonitor());
    this.setVisible(false);

}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    this.setDoubleBuffered(true);
    mySnake.checkLive();
    if(mySnake.isLive()) {
        mySnake.draw(g);
    } else {
        timer.stop();
        this.gameOver(g);
    }
    if(f.isLive()) {
        f.draw(g);
    } else {
        f = new Food();
    }
    mySnake.eatFood(f);
}

private void gameOver(Graphics g) {
    g.setFont(gameOverFont);
}

@Override
public void actionPerformed(ActionEvent e) {
    repaint();
}

private class KeyMonitor extends KeyAdapter {   
    @Override
    public void keyPressed(KeyEvent e) {
        mySnake.keyPressed(e);
    }
}

}

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class WelcomePanel extends JPanel implements ActionListener{
GamePanel gp;
JButton start = null;
JButton help = null;
JTextField inputName = null;

public WelcomePanel(GamePanel gp) {
    this.gp = gp;
    start = new JButton("START");
    start.setBackground(Color.RED);
    start.setBounds(160, 220, 130, 40);
    start.setForeground(Color.RED);
    start.addActionListener(this);

    help = new JButton("HELP");
    help.setBackground(Color.RED);
    help.setBounds(160, 270, 130, 40);
    help.setForeground(Color.RED);
    help.addActionListener(this);

    inputName = new JTextField("请输入你的昵称", 10);
    inputName.setBounds(160, 160, 150, 40);
    this.setBackground(Color.BLACK);
    this.setPreferredSize(new Dimension(GamePanel.B_WIDTH, GamePanel.B_HEIGHT));
    this.setLayout(null);
    this.add(start);
    this.add(inputName);
}

@Override
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == start) {
        gp.playerName = inputName.getText();

System.out.println(gp.playerName);
gp.myJFrame.setContentPane(gp);
gp.setVisible(true);
gp.timer.start();
} else if(e.getSource() == help) {

    }

}

}

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import javax.swing.JFrame;

public class Snake {
GamePanel gp;
Direction dir = Direction.R;
int x, y, size;

private boolean live = true;
private int sX[] = new int[GamePanel.ALL_DOTS];
private int sY[] = new int[GamePanel.ALL_DOTS];

public Snake() {
    size = 2;
    sX[0] = 1 * GamePanel.DOT_SIZE;
    sX[1] = 0 * GamePanel.DOT_SIZE;
    sY[0] = 0 * GamePanel.DOT_SIZE;
    sY[1] = 0 * GamePanel.DOT_SIZE; 
}

public Snake(int x, int y, GamePanel gp) {
    this.x = x;
    this.y = y;
    this.gp = gp;
}

public void draw(Graphics g) {
    move();

    Color c = g.getColor();
    g.setColor(Color.GREEN);
    for(int i=0; i<size; i++) {
        g.fillOval(sX[i], sY[i], GamePanel.DOT_SIZE, GamePanel.DOT_SIZE);
    }
}

public void keyPressed(KeyEvent e) {
    int key = e.getKeyCode();
    switch(key) {
    case KeyEvent.VK_UP :
        if(dir == Direction.D)  break;
        dir = Direction.U; 
        break;
    case KeyEvent.VK_DOWN :
        if(dir == Direction.U)  break;
        dir = Direction.D; 
        break;
    case KeyEvent.VK_LEFT :
        if(dir == Direction.R)  break;
        dir = Direction.L; 
        break;
    case KeyEvent.VK_RIGHT :
        if(dir == Direction.L)  break;
        dir = Direction.R; 
        break;
    }
}

public void move() {
    for(int i=size-1; i>0; i--) {
        sX[i] = sX[(i-1)];
        sY[i] = sY[(i-1)];
    }

    switch(dir) {
    case U :
        sY[0] -= GamePanel.DOT_SIZE;
        break;
    case D :
        sY[0] += GamePanel.DOT_SIZE;
        break;
    case L :
        sX[0] -= GamePanel.DOT_SIZE;
        break;
    case R :
        sX[0] += GamePanel.DOT_SIZE;
        break;
    }

System.out.println(dir);
}

public boolean eatFood(Food f) {
    if(f.fX == sX[0] && f.fY == sY[0]) {
        f.setLive(false);
        this.grow();
        return true;
    }
    return false; 
}

private void grow() {
    size ++;
}

public boolean isLive() {
    return live;
}

public void setLive(boolean live) {
    this.live = live;
}

public void checkLive() {
    if(sX[0] < 0 || sX[0] >= GamePanel.B_WIDTH || sY[0] < 0 || sY[0] >= GamePanel.B_HEIGHT) {
        this.setLive(false);
    } 
    for(int i=1; i<size; i++) {
        if(sX[0] == sX[i] && sY[0] == sY[i]) {
            this.setLive(false);
            break;
        }
    }

}

}

import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;

public class Food {
public int fX;
public int fY;
private boolean live = true;

private static Random r = new Random();

public Food() {
    fX = r.nextInt(GamePanel.B_WIDTH / GamePanel.DOT_SIZE) * GamePanel.DOT_SIZE;
    fY = r.nextInt(GamePanel.B_HEIGHT / GamePanel.DOT_SIZE) * GamePanel.DOT_SIZE;
}

public void draw(Graphics g) {
    Color c = g.getColor();
    g.setColor(Color.RED);
    g.fillOval(fX, fY, GamePanel.DOT_SIZE, GamePanel.DOT_SIZE);
}

public boolean isLive() {
    return live;
}

public void setLive(boolean live) {
    this.live = live;
}

}

public enum Direction {
U, D, L, R
}

按下键盘 keyPressed方法没有被调用啊。。焦点我设置了还是没用啊
跪求大神

2个回答

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.03.13 10:08

主要是你定义了两个类GamePanel和WelcomePanel两个都是继承自JPanel的,但是键盘点击事件是添加到第一个GamePanel上的,一个JFrame中包含两个JPanel不知道它的事件是怎么处理的。
但是可以肯定的是,如果要修正代码的话,最好去掉WelcomePanel类,将其归并到GamePanel上来。
有个同样实现的问题,你完全可以参考:
http://ask.csdn.net/questions/241341

wojiushiwo945you
wojiushiwo945you   Ds   Rxr 2016.03.13 14:36

我找打原因了,是因为你的JFrame中使用了两个JPanel轮换显示的,在点击WelcomePanel的开始按钮后,界面切换显示的是GamePanel,但是该面板没有聚焦,导致它不能接收键盘点击事件。
修正你的WelcomePanel的actionPerformed方法,修正开始按钮的处理代码如下:

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == start) {
            gp.playerName = inputName.getText();

            System.out.println(gp.playerName);
            gp.myJFrame.setContentPane(gp);
            gp.setVisible(true);
            // 必须主动聚焦,才能使它的键盘点击事件触发
            gp.requestFocus();
            gp.timer.start();
        } else if (e.getSource() == help) {
        }

    }
wojiushiwo945you
wojiushiwo945you 回复史蒂芬先生: 对你有帮助的话,请你结贴采纳呗。不枉费我花半个小时给你找问题根源啊。
2 年多之前 回复
C_J33
C_J33 回复毕小宝:谢啦!!!
2 年多之前 回复
wojiushiwo945you
wojiushiwo945you 无论哪个控件、想接受键盘事件、必须先获得“焦点”,组件的requestFocus聚焦。
2 年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
兼容各个浏览器实现键盘响应事件
前端开发中, 响应键盘事件是经常用到的, 而且要求兼容各个浏览器, 方便用到是直接参考就可以了,下面就用 JS 实现一个兼容各个浏览器的通用响应键盘事件的函数:
JAVA模态窗体监听事件无响应的问题
今天在做一个小软件工具中,使用到了模态,由父窗体产生一个子窗体,发现子窗体上的监听事件失效,着实郁闷了一下,搜索了一番,原来setVisible()写在了监听前面,改写到后面就好了。
Jpanel或Jframe添加键盘监听无效
无法实现键盘监是因为没有获取屏幕焦点,将需要监听的控件获取屏幕焦点即可,代码如下: 控件名.setFocusable(true); /*注意要写setVisible(true)后面才行。*/
mfc 关于不响应键盘消息的处理
一:首先介绍键盘消息 系统消息:     ALT,F1,——F24等,是由系统内部处理的,程序本身就存在,比如F1是帮助键。     WM_SYSKEYDOWN     WM_SYSKEYUP     WM_SYSCHAR 非系统消息:     是由我们自己加上去的,     WM_KEYDOWN     WM_KEYUP     WM_CHAR 二:然后介绍虚拟键代
Java日记_17.9.01——点击按钮后,键盘监听失效的原因与解决办法
最近在自学JAVA,听了前辈的安利在做自己的小画板,然后悲剧就发生了,同时添加按钮和键盘监听之后,就产生了如题的问题,一直觉得是自己监听事件注册的不对,改了一天,然后终于找到了原因,真的巨坑啊我觉得qwqwwww! 贴吧有一篇帖子,里面有聚聚分析了问题,稍稍记录一下,以防自己傻乎乎的忘了。 原因: 焦点切换问题。 点击按钮后,焦点就到了按钮上,现在按键盘只能被按钮接收到,而不会
Java中的键盘监听事件KeyListener
Java中的键盘监听事件KeyListener转载请注明出处:http://blog.csdn.net/u012301841/article/details/47284917 最近在巩固java基础,发现java的事件机制设计的很好,一个事件源发出事件的消息,只要其他地方注册监听了这个事件源,就可以得到此事件源发出的消息,从而做响应的改变。 后面去深入了解一下,果然为观察者模式。官方说法为采取“
JS键盘监听事件addkey无eval版
JS键盘监听事件addkey无eval版
窗口对鼠标 键盘 无响应 原因
今天 在写一个mfc对话框程序,结构是在一个对话框中创建 多个对话框(初始化就创建)。根据条件 用ShowWindow(SW_SHOW) 来显示 同时隐藏其他对话框(SW_HIDE).出现 一个问题就是 条件触发后子对话 框显示了但是子对话框不能响应鼠标事件。原因是:在代码编写过程中,忘记 ShowWindow(SW_HIDE),于是出现了2个对话框同时存在。2个对话框都在Show
vue 监听键盘事件
    在使用键盘监听键盘事件时直接绑定没有任何反应。  直接在生命周期中进行绑定就可以了。created:function(){ let _this = this; document.onkeydown = function(e){ let _key = window.event.keyCode; if(_key === 13){ _this.l...
JAVA之键盘,鼠标监听事件
先看一下键盘监听接口的API void keyPressed(KeyEvent e) 按下键时调用。 void keyReleased(KeyEvent e) 当键已被释放时调用。 void keyTyped(KeyEvent e) 键入键时调用。 这里写代码片