简体   繁体   中英

ActionListener don't work

when i press 'A' don't do anything. I'am making the game, and i don't seen any wrong written code.

And if you have sugestion what to put in 2D simple survival game, please tell.

I don't get any error.

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.Ellipse2D;

import javax.swing.*;


public class Player extends JPanel implements ActionListener{
Timer time = new Timer(5, this);
double x = 0; double velX = 2;
double y = 0; double velY = 2;

public void paintComponent(Graphics g){
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    Ellipse2D circle = new Ellipse2D.Double(x,y,40,40);
    g2.fill(circle);
    time.start();
}

public void keyPressed(KeyEvent e){
    int key = e.getKeyCode();
    if(key == KeyEvent.VK_A){
        System.out.println("VK_A"); // When i press 'A' don't print this
        velX = 1;
        x = 1;
        x += velX;
        x += 1;
        //velY = 0;
    }
}



public void actionPerformed(ActionEvent e){
    //x += velX;
    //y += velY;
    //x = x + velX;
    //y = y + velY;
    repaint();
  }
}

You have no JButtons and have called addActionListener(...) to nothing, so it makes sense that it won't work. A solution: add a JButton and add the ActionListener to that button. Also, your question states that the ActionListener doesn't work, but your comment looks to be inside of a defunct KeyListener. This suggests that you really want to check out the Swing tutorials. You can find links to the Swing tutorials and to other Swing resources here: Swing Info .

Other comments:

1) re

I don't get any error.

Lack of compilation errors does not mean that there are no logic errors (as you're finding out).

2) Never start a Timer from within the paintComponent method. This method should be for painting and painting only.

3) To respond to the A keypress, use Key Bindings. The tutorials linked to above will show you how to use them.

For example:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import javax.swing.*;

// public class Player extends JPanel implements ActionListener {
public class Player extends JPanel { // !! avoid having GUI's implement listener interfaces
   private static final int TIME_DELAY = 15; // avoid magic numbers
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   Timer time = new Timer(TIME_DELAY, new TimerListener());
   double x = 0;
   double velX = 2;
   double y = 0;
   double velY = 2;

   public Player() {
      // start timer here!
      time.start();

      setKeyBindings();
   }

   private void setKeyBindings() {
      // get action and input maps
      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      // get keystroke
      KeyStroke aKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0);

      // bind keystroke with an action
      inputMap.put(aKeyStroke, aKeyStroke.toString());
      actionMap.put(aKeyStroke.toString(), new A_Action());
   }

   @Override
   //!! public void paintComponent(Graphics g) {
   protected void paintComponent(Graphics g) {  // should be protected not public
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      Ellipse2D circle = new Ellipse2D.Double(x, y, 40, 40);
      g2.fill(circle);
   }

   @Override //!! make bigger
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class A_Action extends AbstractAction {
      @Override
      public void actionPerformed(ActionEvent e) {
         System.out.println("A key pressed");
         x++;
         y++;
         repaint();
      }
   }

   public void actionPerformed(ActionEvent e) {
      // x += velX;
      // y += velY;
      // x = x + velX;
      // y = y + velY;
      repaint();
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         // TODO: move x and y
         repaint();
      }
   }

   private static void createAndShowGui() {
      Player mainPanel = new Player();

      JFrame frame = new JFrame("Player");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

Here's a more complete example, one that does all movement within the Timer's ActionListener. It uses an enum called Direction as well as a Map that binds the four Direction enum values to a boolean. The Key Bindings will change the boolean in the Map and that is it. For instance if the up arrow is pressed, then the Map's Boolean associated with Direction.UP will be true. When the key has been released, the Map value associated with the same Direction.UP key will be changed to false. The Timer's ActionListener will iterate through the four Direction enums, checking the Map value for each enum, and then move the sprite in the direction stipulated by the Direction if the associated boolean is true. Benefits include the ability to respond to multiple key presses at once:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Ellipse2D;
import java.util.EnumMap;
import java.util.Map;
import javax.swing.*;

@SuppressWarnings("serial")
public class MoveCircle extends JPanel { 
   private static final int TIME_DELAY = 15; // avoid magic numbers
   private static final int PREF_W = 600;
   private static final int PREF_H = PREF_W;
   Timer time = new Timer(TIME_DELAY, new TimerListener());

   // key presses and releases will change the boolean values held in this Map
   // When an arrow key is pressed, the direction-corresponding boolean is set true
   // and likewise when the arrow key is released the direction corresponding boolean is false
   private Map<Direction, Boolean> dirMap = new EnumMap<>(Direction.class);
   private double x = 0;
   private double velX = 2;
   private double y = 0;
   private double velY = 2;

   public MoveCircle() {
      setKeyBindings();
      time.start();      
   }

   private void setKeyBindings() {
      int condition = WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition);
      ActionMap actionMap = getActionMap();

      // iterate through all the Direction enums
      for (Direction direction : Direction.values()) {
         // set all values to false
         dirMap.put(direction, false);

         // create two key strokes, one for pressed and one for released
         int keyValue = direction.getKeyValue();
         KeyStroke pressedKey = KeyStroke.getKeyStroke(keyValue, 0, false);
         KeyStroke releasedKey = KeyStroke.getKeyStroke(keyValue, 0, true);

         // create two Actions, one for pressed, one for released
         Action pressedAction = new KeyAction(direction, true);
         Action releasedAction = new KeyAction(direction, false);

         // add keystroke to inputMap and use keystroke's toString as binding link
         inputMap.put(pressedKey, pressedKey.toString());
         inputMap.put(releasedKey, releasedKey.toString());

         // link binding links to our actions
         actionMap.put(pressedKey.toString(), pressedAction);
         actionMap.put(releasedKey.toString(), releasedAction);
      }
   }

   @Override
   protected void paintComponent(Graphics g) {  
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;

      // draw smooth circles
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
      Ellipse2D circle = new Ellipse2D.Double(x, y, 40, 40);
      g2.fill(circle);
   }

   @Override 
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class KeyAction extends AbstractAction {
      private Direction direction;
      private boolean pressed;

      public KeyAction(Direction direction, boolean pressed) {
         this.direction = direction;
         this.pressed = pressed;               
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         dirMap.put(direction, pressed); // key press simply changes the map, that's it.
      }
   }

   private class TimerListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         // if JPanel no longer displayed, stop the Timer
         if (!MoveCircle.this.isDisplayable()) {
            ((Timer) e.getSource()).stop();
         }
         // here's the key: iterate through the Direction enum
         for (Direction direction : Direction.values()) {
            // get corresponding boolean from dirMap
            // and if true, change location of x and y
            if (dirMap.get(direction)) {
               x += velX * direction.getDeltaX();
               y += velY * direction.getDeltaY();
            }
         }
         repaint();
      }
   }

   private static void createAndShowGui() {
      MoveCircle mainPanel = new MoveCircle();

      JFrame frame = new JFrame("Move Circle");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

enum Direction {
   UP("Up", KeyEvent.VK_UP, 0, -1),
   DOWN("Down", KeyEvent.VK_DOWN, 0, 1),
   LEFT("Left", KeyEvent.VK_LEFT, -1, 0),
   RIGHT("Right", KeyEvent.VK_RIGHT, 1, 0);

   private String text; 
   private int keyValue; // KeyEvent.VK_?
   private int deltaX; 
   private int deltaY;

   Direction(String text, int keyValue, int deltaX, int deltaY) {
      this.text = text;
      this.keyValue = keyValue;
      this.deltaX = deltaX;
      this.deltaY = deltaY;
   }

   public String getText() {
      return text;
   }

   public int getKeyValue() {
      return keyValue;
   }

   @Override
   public String toString() {
      return text;
   }

   public int getDeltaX() {
      return deltaX;
   }

   public int getDeltaY() {
      return deltaY;
   }

}
public class Player extends JPanel implements ActionListener, KeyListener{

You should also implement the keylistener to listen for keypresses. The ActionListener handles the button clicks.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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