Java- 键绑定不工作/未调用 actionPerformed

Java- Key Bindings not working / actionPerformed not being called

感谢在上一个问题中帮助我的人,我终于学会了如何在 java 中使用图形,但现在我无法使用键绑定。我知道图形方法在我需要时被调用,并且我认为我已经正确声明了我的键绑定,但是 'actionPerformed()' 方法不会调用。我尝试使用单例模式让我的玩家对象跨越 类,我觉得它以某种方式搞砸了其他一切。我试着浏览了很多与我的问题相关的其他问题,但我仍然无法弄清楚,除非我忽略了一些明显的东西。如果你们中的一位伟大的编程向导能够破解这个,我将不胜感激:

import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.KeyStroke;

public class Player {
    private int xLoc, yLoc;
    private boolean isFiring;
    private String filename;
    private ImageIcon imageicon;
    private URL imgURL;

    private static Player player;

    public Player(int xl, int yl, boolean fire, String name){
        xLoc = xl;
        yLoc = yl;
        isFiring = fire;
        filename = name;
        imgURL = getClass().getResource(name);
        imageicon = new ImageIcon(imgURL);
    }

    public static Player getInstance(){
        if(player == null){
            player = new Player(0,0,false,"Dog.jpg");
        }
        return player;
    }

    public void fire(){

    }

    public int getX(){
        return xLoc;
    }
    public int getY(){
        return yLoc;
    }
    public void newX(int x){
        xLoc = x;
    }
    public ImageIcon getImg() {
        return imageicon;
    }
    public void newImg(ImageIcon ii){
        imageicon = ii;
    }
    public URL getURL(){
        return imgURL;
    }
    public void newURL(String n){
        imgURL = getClass().getResource(n);
    }
    public void updateObject(){
        imageicon = new ImageIcon(imgURL);
    }
}

.

import java.awt.Graphics;
import java.net.URL;

import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class GamePanel extends JPanel{
    int nameSwap = 0;
    Player player;
    public GamePanel(){
        player = Player.getInstance();
        repaint();
        System.out.println("Repaint method called");

        this.getInputMap().put(KeyStroke.getKeyStroke("A"), "moveLeft");
        this.getActionMap().put("moveLeft", new MoveLR(-1));

        this.getInputMap().put(KeyStroke.getKeyStroke("D"), "moveRight");
        this.getActionMap().put("moveRight", new MoveLR(1));

        this.getInputMap().put(KeyStroke.getKeyStroke("S"), "fire");
        this.getActionMap().put("fire", new Fire());
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.drawImage(player.getImg().getImage(), player.getX(), player.getY(), 50, 50, null);
        //System.out.println("Graphics method called");
    }
}

.

import java.awt.Color;

import javax.swing.JFrame;

public class Window {

    public Window() {
        JFrame frame = new JFrame("Epic Game");
        frame.setSize(800,600);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        GamePanel panel = new GamePanel();
        frame.add(panel);

        frame.setVisible(true);

        while(true){
            panel.repaint();
        }
    }

    public static void main(String[] args){
        Window window = new Window();
    }
}   

.

import java.awt.event.ActionEvent;
import java.beans.PropertyChangeListener;

import javax.swing.Action;

public class MoveLR implements Action{
    private int moveVal;
    Player player;
    public MoveLR(int mv){
        moveVal = mv;
        player = Player.getInstance();
        System.out.println("New MoveLR object made");
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub
        player.newX(player.getX() + 1);
        System.out.println("actionPerformed() called");
    }

    @Override
    public void addPropertyChangeListener(PropertyChangeListener arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public Object getValue(String arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean isEnabled() {
        // TODO Auto-generated method stub
        return false;
    }

    @Override
    public void putValue(String arg0, Object arg1) {
        // TODO Auto-generated method stub

    }

    @Override
    public void removePropertyChangeListener(PropertyChangeListener arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void setEnabled(boolean arg0) {
        // TODO Auto-generated method stub

    }
}

您使用了错误的 InputMap。使用getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)。这样,您将绑定到当 JPanel 没有焦点但显示在 window 中时处于活动状态的键。默认的 InputMap 是用于 JComponent.WHEN_FOCUSED 的那个,只有当绑定的组件有焦点时才有效,这不是你想要做的或使用的。

this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), 
        "moveLeft");

还使用扩展 AbstractAction 的 类,而不是实现 Action 的那些,因为您的 Actions 没有完全连接。是的,只要您有对 JPanel 的引用,您就可以在 actionPerformed 结束时重新绘制,ActionEvent 可以为您提供。

测试程序:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class Window {

   public Window() {
      JFrame frame = new JFrame("Epic Game");
      frame.setSize(800, 600);
      frame.setLocationRelativeTo(null);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      GamePanel panel = new GamePanel();
      frame.add(panel);

      frame.setVisible(true);

      // !! while (true) {
      // panel.repaint();
      // }
   }

   public static void main(String[] args) {
      new Window();
   }
}

@SuppressWarnings("serial")
class GamePanel extends JPanel {
   int nameSwap = 0;
   Player player;

   public GamePanel() {
      player = Player.getInstance();
      repaint();
      System.out.println("Repaint method called");

      this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), "moveLeft");
      this.getActionMap().put("moveLeft", new MoveLR(-1));

      this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("D"), "moveRight");
      this.getActionMap().put("moveRight", new MoveLR(1));

      this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("S"), "fire");
      this.getActionMap().put("fire", new Fire());
   }

   public void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.drawImage(player.getImg().getImage(), player.getX(), player.getY(), 50,
            50, null);
      // System.out.println("Graphics method called");
   }
}

class Player {
   private int xLoc, yLoc;
   private boolean isFiring;
   private String filename;
   private ImageIcon imageicon;
   // !! private URL imgURL;

   private static Player player;

   public Player(int xl, int yl, boolean fire, String name) {
      BufferedImage img = new BufferedImage(20, 20, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = img.createGraphics();
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g2.setColor(Color.red);
      g2.fillOval(2, 2, 16, 16);
      g2.dispose();
      imageicon = new ImageIcon(img);
      xLoc = xl;
      yLoc = yl;
      isFiring = fire;
      filename = name;
      // !! imgURL = getClass().getResource(name);
      // imageicon = new ImageIcon(imgURL);
   }

   public static Player getInstance() {
      if (player == null) {
         player = new Player(0, 0, false, "Dog.jpg");
      }
      return player;
   }

   public void fire() {

   }

   public int getX() {
      return xLoc;
   }

   public int getY() {
      return yLoc;
   }

   public void newX(int x) {
      xLoc = x;
   }

   public ImageIcon getImg() {
      return imageicon;
   }

   public void newImg(ImageIcon ii) {
      imageicon = ii;
   }

   // !! public URL getURL(){
   // return imgURL;
   // }
   // !! public void newURL(String n){
   // imgURL = getClass().getResource(n);
   // }
   public void updateObject() {
      // !! imageicon = new ImageIcon(imgURL);
      System.out.println("update object called");
   }
}

class MoveLR extends AbstractAction {
   private int moveVal;
   Player player;

   public MoveLR(int mv) {
      moveVal = mv;
      player = Player.getInstance();
      System.out.println("New MoveLR object made");
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      // TODO Auto-generated method stub
      player.newX(player.getX() + moveVal);
      ((JPanel) e.getSource()).repaint();
      System.out.println("actionPerformed() called");
   }

}

class Fire extends AbstractAction {
   public Fire() {
      System.out.println("Fire created");
   }

   @Override
   public void actionPerformed(ActionEvent arg0) {
      System.out.println("Fire called");
   }
}