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 回复史蒂芬先生: 对你有帮助的话,请你结贴采纳呗。不枉费我花半个小时给你找问题根源啊。
一年多之前 回复
C_J33
C_J33 回复毕小宝:谢啦!!!
一年多之前 回复
wojiushiwo945you
wojiushiwo945you 无论哪个控件、想接受键盘事件、必须先获得“焦点”,组件的requestFocus聚焦。
接近 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!