按键时,按键侦听器不工作

时间:2012-10-28 23:04:03

标签: java swing graphics keylistener

我在尝试让我的代码在屏幕上移动播放器(Ship)时遇到了很多麻烦。我可以让行星画在屏幕和玩家的船上,但我无法弄清楚如何实现keyListener至少打印出来的东西。提前感谢您的帮助!

    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import java.awt.Canvas;
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.Toolkit;
    import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;


    public class MapPanel extends JPanel {
public static final int WIDTH = 25;
 public static final int HEIGHT = 20;
 int zone = 0;
 private int xValue;
 private int yValue;
 private Color color;
 public Planet[][] planetGrid = new Planet[WIDTH][HEIGHT];
 static Player currPlayer = new Player("h");
 static Universe universe = new Universe(currPlayer);

 /**
 * Create the panel.
 */
 public MapPanel(Universe univ, Player p) {
    this.universe = univ;
    currPlayer = p;
    int i = 0;
    this.setSize(new Dimension(450,450));
    setVisible( true );
    //this.addKeyListener(new KeyController());
     KeyController kc = new KeyController();
     this.addKeyListener(kc);
    repaint();


 }


 /**
  * Draw method to draw the playing field
  * @param g Graphics object
  * @param tileDimension dimension of the tile
  */
 public void draw(Graphics g)
 {
 universe.draw(g);

    //    KeyController key = new KeyController();
 }
 public void paintComponent(Graphics g) {
     super.paintComponent(g);
     draw(g);
 }
 public static void main(String[] args)
 {
     MapPanel mp = new MapPanel(universe, currPlayer);
     JFrame f = new JFrame();
     f.add(mp);
     f.setSize(new Dimension(450,450));
     f.setVisible(true);
     f.setFocusable(true);


 }
 private class KeyController implements KeyListener {
     public KeyController()
     {
         System.out.println("ghgh");
         setFocusable(true);
        // addKeyListener(this);
     }
        @Override
        public void keyPressed(final KeyEvent key) {
            System.out.println("fgfgf");
            if (currPlayer != null) {

                int oldX = currPlayer.getPosition().x;
                int oldY = currPlayer.getPosition().y;

                switch (key.getKeyCode()) {
                    case KeyEvent.VK_RIGHT:
                      currPlayer.setPosition(new Point(oldX+1, oldY)); //move right
                      System.out.println("RIGHT");
                        break;
                    case KeyEvent.VK_LEFT:
                          currPlayer.setPosition(new Point(oldX-1, oldY));         //move left
                        break;
                    case KeyEvent.VK_DOWN:
                          currPlayer.setPosition(new Point(oldX, oldY+1));         //move down
                        break;
                    case KeyEvent.VK_UP:
                          currPlayer.setPosition(new Point(oldX, oldY-1));         //move up
                        break;
                }

            }
            repaint();
        }
        @Override
        public void keyReleased(KeyEvent e) {
            System.out.println("ggg");
        }
        @Override
        public void keyTyped(KeyEvent e) {
            System.out.println("typeeeddd");
        }
    }





    }

2 个答案:

答案 0 :(得分:2)

KeyListener不是实现结果的最合适方法。

最好使用key bindings API。

除了简化代码之外,它还允许您更好地集中控制何时触发密钥。

答案 1 :(得分:0)

在这里我设计了一个类似于你的应用程序,你可以使用箭头键,n在移动的船上投掷炸弹(这是我几年前的项目:)),设计一个主要方法来运行,希望这会求助:

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


/**
* This panel implements a simple arcade game in which the user tries to blow
* up a "submarine" (a black oval) by dropping "depth charges" (a red disk) from
* a "boat" (a blue roundrect).  The user moves the boat with the left- and
* right-arrow keys and drops the depth charge with the down-arrow key.
* The sub moves left and right erratically along the bottom of the panel.
*/
public class SubKillerPanel extends JPanel {

private Timer timer;        // Timer that drives the animation.

private int width, height;  // The size of the panel -- the values are set
                           //    the first time the paintComponent() method
                           //    is called.  This class is not designed to
                           //    handle changes in size; once the width and
                           //    height have been set, they are not changed.
                           //    Note that width and height cannot be set
                           //    in the constructor because the width and
                           //    height of the panel have not been set at
                           //    the time that the constructor is called.

private Boat boat;          // The boat, bomb, and sub objects are defined
private Bomb bomb;          //    by nested classes Boat, Bomb, and Submarine,
private Submarine sub;      //    which are defined later in this class.
                           //    Note that the objects are created in the
                           //    paintComponent() method, after the width
                           //    and height of the panel are known.


 /**
* The constructor sets the background color of the panel, creates the
* timer, and adds a KeyListener, FocusListener, and MouseListener to the
* panel.  These listeners, as well as the ActionListener for the timer
* are defined by anonymous inner classes.  The timer will run only
* when the panel has the input focus.
*/
public SubKillerPanel() {

  setBackground(Color.GREEN);

  ActionListener action = new ActionListener() {
           // Defines the action taken each time the timer fires.
     public void actionPerformed(ActionEvent evt) {
        if (boat != null) {
           boat.updateForNewFrame();
           bomb.updateForNewFrame();
           sub.updateForNewFrame();
        }
        repaint();
     }
  };
  timer = new Timer( 30, action );  // Fires every 30 milliseconds.

  addMouseListener( new MouseAdapter() {
          // The mouse listener simply requests focus when the user
          // clicks the panel.
     public void mousePressed(MouseEvent evt) {
        requestFocus();
     }
  } );

  addFocusListener( new FocusListener() {
         // The focus listener starts the timer when the panel gains
         // the input focus and stops the timer when the panel loses
         // the focus.  It also calls repaint() when these events occur.
     public void focusGained(FocusEvent evt) {
        timer.start();
        repaint();
     }
     public void focusLost(FocusEvent evt) {
        timer.stop();
        repaint();
     }
  } );

  addKeyListener( new KeyAdapter() {
         // The key listener responds to keyPressed events on the panel. Only
         // the left-, right-, and down-arrow keys have any effect.  The left- and
         // right-arrow keys move the boat while down-arrow releases the bomb.
     public void keyPressed(KeyEvent evt) {
        int code = evt.getKeyCode();  // Which key was pressed?
        if (code == KeyEvent.VK_LEFT) {
             // Move the boat left.  (If this moves the boat out of the frame, its
             // position will be adjusted in the boat.updateForNewFrame() method.)
           boat.centerX -= 15;
        }
        else if (code == KeyEvent.VK_RIGHT) {
             // Move the boat right.  (If this moves boat out of the frame, its
             // position will be adjusted in the boat.updateForNewFrame() method.)
           boat.centerX += 15;
        }
        else if (code == KeyEvent.VK_DOWN) {
              // Start the bomb falling, if it is not already falling.
           if ( bomb.isFalling == false )
              bomb.isFalling = true;
        }
     }
  } );

 } // end constructor


/**
* The paintComponent() method draws the current state of the game.  It
* draws a gray or cyan border around the panel to indicate whether or not
* the panel has the input focus.  It draws the boat, sub, and bomb by
* calling their respective draw() methods.
*/
public void paintComponent(Graphics g) {

  super.paintComponent(g);  // Fill panel with background color, green.

  if (boat == null) {
        // The first time that paintComponent is called, it assigns
        // values to the instance variables.
     width = getWidth();
     height = getHeight();
     boat = new Boat();
     sub = new Submarine();
     bomb = new Bomb();
  }

  if (hasFocus())
     g.setColor(Color.CYAN);
  else {
     g.setColor(Color.RED);
     g.drawString("CLICK TO ACTIVATE", 20, 30);
     g.setColor(Color.GRAY);
  }
  g.drawRect(0,0,width-1,height-1);  // Draw a 3-pixel border.
  g.drawRect(1,1,width-3,height-3);
  g.drawRect(2,2,width-5,height-5);

  boat.draw(g);
  sub.draw(g);
  bomb.draw(g);

 } // end drawFrame()


/**
* This nested class defines the boat.  Note that its constructor cannot
* be called until the width of the panel is known!
*/
private class Boat {
  int centerX, centerY;  // Current position of the center of the boat.
  Boat() { // Constructor centers the boat horizontally, 80 pixels from top.
     centerX = width/2;
     centerY = 80;
  }
  void updateForNewFrame() { // Makes sure boat has not moved off screen.
     if (centerX < 0)
        centerX = 0;
     else if (centerX > width)
        centerX = width;
  }
  void draw(Graphics g) {  // Draws the boat at its current location.
     g.setColor(Color.BLUE);
     g.fillRoundRect(centerX - 40, centerY - 20, 80, 40, 20, 20);
  }
 } // end nested class Boat


 /**
 * This nested class defines the bomb.
 */
 private class Bomb {
  int centerX, centerY; // Current position of the center of the bomb.
  boolean isFalling;    // If true, the bomb is falling; if false, it
                        // is attached to the boat.
  Bomb() { // Constructor creates a bomb that is initially attached to boat.
     isFalling = false;
  }
  void updateForNewFrame() {  // If bomb is falling, take appropriate action.
     if (isFalling) {
        if (centerY > height) {
              // Bomb has missed the submarine.  It is returned to its
              // initial state, with isFalling equal to false.
           isFalling = false;
        }
        else if (Math.abs(centerX - sub.centerX) <= 36 &&
                             Math.abs(centerY - sub.centerY) <= 21) {
              // Bomb has hit the submarine.  The submarine
              // enters the "isExploding" state.
           sub.isExploding = true;
           sub.explosionFrameNumber = 1;
           isFalling = false;  // Bomb reappears on the boat.
        }
        else {
             // If the bomb has not fallen off the panel or hit the
             // sub, then it is moved down 10 pixels.
           centerY += 10;
        }
     }
  }
  void draw(Graphics g) {  // Draw the bomb.
     if ( ! isFalling ) {  // If not falling, set centerX and CenterY
                          // to show the bomb on the bottom of the boat.
        centerX = boat.centerX;
        centerY = boat.centerY + 23;
     }
     g.setColor(Color.RED);
     g.fillOval(centerX - 8, centerY - 8, 16, 16);
  }
 } // end nested class Bomb


/**
* This nested class defines the sub.  Note that its constructor cannot
* be called until the width of the panel is known!
*/
private class Submarine {
  int centerX, centerY; // Current position of the center of the sub.
  boolean isMovingLeft; // Tells whether the sub is moving left or right
  boolean isExploding;  // Set to true when the sub is hit by the bomb.
  int explosionFrameNumber;  // If the sub is exploding, this is the number
                             //   of frames since the explosion started.
  Submarine() {  // Create the sub at a random location 40 pixels from bottom.
     centerX = (int)(width*Math.random());
     centerY = height - 40;
     isExploding = false;
     isMovingLeft = (Math.random() < 0.5);
  }
  void updateForNewFrame() { // Move sub or increase explosionFrameNumber.
     if (isExploding) {
           // If the sub is exploding, add 1 to explosionFrameNumber.
           // When the number reaches 15, the explosion ends and the
           // sub reappears in a random position.
        explosionFrameNumber++;
        if (explosionFrameNumber == 15) {
           centerX = (int)(width*Math.random());
           centerY = height - 40;
           isExploding = false;
           isMovingLeft = (Math.random() < 0.5);
        }
     }
     else { // Move the sub.
        if (Math.random() < 0.04) {
              // In one frame out of every 25, on average, the sub
              // reverses its direction of motion.
           isMovingLeft = ! isMovingLeft;
        }
        if (isMovingLeft) {
              // Move the sub 5 pixels to the left.  If it moves off
              // the left edge of the panel, move it back to the left
              // edge and start it moving to the right.
           centerX -= 5;
           if (centerX <= 0) {
              centerX = 0;
              isMovingLeft = false;
           }
        }
        else {
              // Move the sub 5 pixels to the right.  If it moves off
              // the right edge of the panel, move it back to the right
              // edge and start it moving to the left.
           centerX += 5;
           if (centerX > width) {
              centerX = width;
              isMovingLeft = true;
           }
        }
     }
  }
  void draw(Graphics g) {  // Draw sub and, if it is exploding, the explosion.
     g.setColor(Color.BLACK);
     g.fillOval(centerX - 30, centerY - 15, 60, 30);
     if (isExploding) {
            // Draw an "explosion" that grows in size as the number of
            // frames since the start of the explosion increases.
        g.setColor(Color.YELLOW);
        g.fillOval(centerX - 4*explosionFrameNumber,
              centerY - 2*explosionFrameNumber,
              8*explosionFrameNumber,
              4*explosionFrameNumber);
        g.setColor(Color.RED);
        g.fillOval(centerX - 2*explosionFrameNumber,
              centerY - explosionFrameNumber/2,
              4*explosionFrameNumber,
              explosionFrameNumber);
     }
  }
 } // end nested class Submarine


} // end class SubKiller