当我的JPanel与其他组件(例如JLabel,JButton等)一起位于JCanvas文件下时,我正在尝试在JPanel中实现keylistener。但是,敲击键后,keylistener没有响应。我添加了关键侦听器,并将JPanel设置为可聚焦。我应该怎么做才能解决这个问题? 代码如下所示:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
public class Main extends JFrame implements ActionListener{
private static final long serialVersionUID = 1L;
protected static final String FRAME_TITLE = "Coco's Drone";
protected static final int TIMER_DELAY=100;//ms
protected static final int FRAME_WIDTH=1000;
protected static final int FRAME_HEIGHT=650;
protected static final int CANVAS_WIDTH=1000;
protected static final int CANVAS_HEIGHT=450;
protected static final String IMAGE_TITLE= "Rocket.png"; //Change the image route
protected Graphics g = getGraphics();
protected static Boolean initial=true;
protected GraphicCanvas canvas;
protected JLabel instruction,instruction_text,score,title;
protected JButton start;
protected Timer timer;
protected Fuels fuel;
protected Live rocket;
static Random rand = new Random();
public static int[] height_1= {0,0,0,0,0,0,0,0,0,0};
public static int[] height_2= {0,0,0,0,0,0,0,0,0,0};
public static int x=20;
public static int y=0;
public static int scores=100;
public static int rotation=0;
public static int v=0;
static int lives=3;
public Main() {
super();
initGraphics();
initTimer();
//initHandlers();
}
protected void initGraphics() {
setTitle(FRAME_TITLE);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel panel=new JPanel();
panel.setPreferredSize(new Dimension(1000, 200));
add(panel,BorderLayout.NORTH);
panel.setLayout(new BorderLayout());
//West title panel
JPanel panelW=new JPanel();
panelW.setBackground(Color.gray);
panelW.setPreferredSize(new Dimension(300, 150));
panelW.setBorder( new EmptyBorder( 10, 10, 0, 0 ) );
panelW.setLayout(new GridLayout(3,1));
panel.add(panelW,BorderLayout.WEST);
score=new JLabel("Score: 100 ");
score.setFont(new Font("Serif", Font.ITALIC,20));
panelW.add(score);
rocket=new Live();
panelW.add(rocket);
fuel=new Fuels();
panelW.add(fuel);
//South title panel
start=new JButton("START");
start.setPreferredSize(new Dimension(40, 40));
start.setBackground(Color.gray);
start.setOpaque(true);
start.setFont(new Font("Serif", Font.BOLD, 20));
start.addActionListener(this);
panel.add(start,BorderLayout.SOUTH);
//East title panel
instruction=new JLabel("<html>INSTRUCTION: Please use arrow keys to control the drone. You must land safely on the red block before funning out of fuel. Good luck!</html>");
instruction.setOpaque(true);
instruction.setBackground(Color.gray);
instruction.setFont(new Font("Serif", Font.ITALIC, 20));
instruction.setPreferredSize(new Dimension(300, 100));
panel.add(instruction,BorderLayout.EAST);
//Center title panel
title=new JLabel("DRONE PILOT");
title.setHorizontalAlignment(JLabel.CENTER);
title.setForeground(Color.white);
title.setOpaque(true);
title.setBackground(Color.gray);
panel.add(title,BorderLayout.CENTER);
title.setFont(new Font("Serif", Font.BOLD, 50));
title.setVerticalAlignment(JLabel.CENTER);
title.setHorizontalAlignment(JLabel.CENTER);
canvas=new GraphicCanvas();
canvas.setPreferredSize(new Dimension(1000, 450));
canvas.addKeyListener(new KeyHandler());
canvas.setFocusable(true);
canvas.requestFocusInWindow();
add(canvas,BorderLayout.CENTER);
pack();
}
protected void initTimer() {
timer=new Timer(TIMER_DELAY, new TimerHandler());
}
protected void initHandlers() {
canvas.addKeyListener(new KeyHandler());
}
@Override
public void actionPerformed(ActionEvent e) {
timer.start();
}
public static void initCharacters(Graphics g) {
BufferedImage live=new BufferedImage(60, 60,BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d=(Graphics2D)g; // Create a Java2D version of g.
try {
live=ImageIO.read(new File(IMAGE_TITLE));
}
catch(IOException e) {
System.out.println("no file.");
}
GraphicCanvas.boundary();
int w = live.getWidth(), h = live.getHeight();
double sin = Math.abs(Math.sin(Math.toRadians(rotation))), cos = Math.abs(Math.cos(Math.toRadians(rotation)));
int neww = (int)Math.floor(w*cos+h*sin), newh = (int)Math.floor(h*cos+w*sin);
//g2d.drawImage(live,x,y,60,60,this);
g2d.rotate(Math.toRadians(rotation), w/2 , h/2 );
g2d.translate((neww-w)/2, (newh-h)/2);
g2d.drawImage(live,x,y,60,60,null);
}
protected static class GraphicCanvas extends JPanel{
public void level(Graphics g) {
int height_u,height_b;
g.setColor(Color.gray);
if(initial==true) {
for(int i=0;i<10;i++) {
height_1[i]=rand.nextInt(5)*20+50;
height_2[i]=rand.nextInt(5)*20+50;
}
y=390-height_2[0];
}
for(int i=0;i<10;i++) {
height_u=height_1[i];
height_b=height_2[i];
g.fillRect(i*100, 0, 100, height_u);
if(i==9) {
g.setColor(Color.red);
}
g.fillRect(i*100, 450-height_b, 100, height_b);
}
}
public static void boundary() {
for(int i=0;i<10;i++) {
if((x>i*100-60)&&x<=((i+1)*100-60)) {
if(y<height_1[i]) {
y+=1;
scores-=1;
}//upper boundary
if(y>(390-height_2[i])) {
y-=1;
scores-=1;
}//lower boundary
}
}
}
@Override
public boolean isFocusable() {
return true;
}
@Override
public void paintComponent(Graphics g) {
level(g);
if(initial==false) {
initCharacters(g);
}
}
}
protected class KeyHandler implements KeyListener{
@Override
public void keyPressed(KeyEvent e) {
System.out.println("check keypress");
switch(e.getKeyCode()) {
case KeyEvent.VK_RIGHT:
turnRight();
movement();
break;
case KeyEvent.VK_LEFT:
turnLeft();
movement();
break;
case KeyEvent.VK_UP:
forward();
movement();
break;
}
}
@Override
public void keyReleased(KeyEvent e) {System.out.println("check keyrelease");}
@Override
public void keyTyped(KeyEvent e) {System.out.println("check keytype");}
public void restart() {
if(Fuel.x==0) {
x=20;
y=390-height_2[0];
rotation=0;
stop();
}
}
public void turnRight() {
rotation-=1;
}
public void turnLeft() {
rotation+=1;
}
public void stop() {
v=0;
}
public void forward() {
v+=1;
}
public void movement() {
x+=v*Math.cos(Math.toRadians(rotation));
y-=v*Math.sin(Math.toRadians(rotation))-4.9*0.1;
}
}
protected class TimerHandler implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
canvas.repaint();
fuel.repaint();
rocket.repaint();
initial=false;
score.setText("Score: "+scores);
}
}
protected class Fuels extends JComponent{
int fuel_x;
public void paintComponent(Graphics g) {
if(fuel_x==0 && lives >0) {
lives-=1;
fuel_x=300;
}
fuel_x-=1;
g.setColor(Color.red);
g.fillRect(0,10,fuel_x,30);
}
}
protected class Live extends JComponent{
BufferedImage live=new BufferedImage(40, 40,BufferedImage.TYPE_INT_ARGB);;
public Live() {
try {
live=ImageIO.read(new File(IMAGE_TITLE));
}
catch(IOException e) {
System.out.println("no file.");
}
}
public void paintComponent(Graphics g) {
if(lives==2) {
g.drawImage(live,0,0,40,40,this);
g.drawImage(live,50,0,40,40,this);
}
else if(lives==1) {
g.drawImage(live,0,0,40,40,this);
}
else if(lives<=0){
}
else {
g.drawImage(live,0,0,40,40,this);
g.drawImage(live,50,0,40,40,this);
g.drawImage(live,100,0,40,40,this);
}
}
}
public static void main(String[] args) {
Main gui = new Main();
gui.setVisible(true);
}