简体   繁体   English

ActionListener不起作用

[英]ActionListener don't work

when i press 'A' don't do anything. 当我按'A'时什么都不做。 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. 如果你有消化什么放在2D简单生存游戏,请告诉。

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. 你没有JButton并且没有调用addActionListener(...) ,所以它是行不通的。 A solution: add a JButton and add the ActionListener to that button. 解决方案:添加JButton并将ActionListener添加到该按钮。 Also, your question states that the ActionListener doesn't work, but your comment looks to be inside of a defunct KeyListener. 此外,您的问题表明ActionListener不起作用,但您的注释看起来在一个已失效的KeyListener中。 This suggests that you really want to check out the Swing tutorials. 这表明你真的想看看Swing教程。 You can find links to the Swing tutorials and to other Swing resources here: Swing Info . 您可以在此处找到Swing教程和其他Swing资源的链接: Swing Info

Other comments: 其他的建议:

1) re 1)重新

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. 2)永远不要在paintComponent方法中启动Timer。 This method should be for painting and painting only. 此方法仅适用于绘画和绘画。

3) To respond to the A keypress, use Key Bindings. 3)要响应A按键,请使用键绑定。 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. 这是一个更完整的示例,它可以在Timer的ActionListener中完成所有移动。 It uses an enum called Direction as well as a Map that binds the four Direction enum values to a boolean. 它使用名为Direction的枚举以及将四个方向枚举值绑定到布尔值的Map。 The Key Bindings will change the boolean in the Map and that is it. Key Bindings将改变Map中的布尔值,即它。 For instance if the up arrow is pressed, then the Map's Boolean associated with Direction.UP will be true. 例如,如果按下向上箭头,则与Direction.UP关联的Map的布尔值将为true。 When the key has been released, the Map value associated with the same Direction.UP key will be changed to false. 释放该键后,与相同Direction.UP键关联的Map值将更改为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. Timer的ActionListener将迭代四个方向枚举,检查每个枚举的Map值,然后如果关联的布尔值为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. 您还应该实现keylistener来监听按键。 The ActionListener handles the button clicks. ActionListener处理按钮单击。

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

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