简体   繁体   English

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

[英]Key Listener not working when being pressed

I'm having a lot of trouble trying to make my code move a player (Ship) around a screen. 我在尝试让我的代码在屏幕上移动播放器(Ship)时遇到了很多麻烦。 I can get the planets to draw on the screen and the the player ship but I can not figure out how to implement the keyListener to at least print out something. 我可以让行星画在屏幕和玩家的船上,但我无法弄清楚如何实现keyListener至少打印出来的东西。 Thank you in advance for all the help! 提前感谢您的帮助!

    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");
        }
    }





    }

KeyListener is not the most appropriate method to achieve your results. KeyListener不是实现结果的最合适方法。

It would be better to use the key bindings API. 最好使用密钥绑定 API。

Apart from simplifying the code, it will also allow you to provide better focus control over when the keys should triggered. 除了简化代码之外,它还允许您在触发键时提供更好的焦点控制。

here i have design an application similar to yours,where you can use arrow keys,n throw a bomb on the moving ship(this was my project few years back :) ),design a main method to run,hope this will help: 在这里我设计了一个类似于你的应用程序,在那里你可以使用箭头键,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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM