Java KeyListeners的麻烦......可能还有程序本身

时间:2011-12-06 02:01:35

标签: java swing keylistener

所以这个程序的目标(以及最后的起点)是按箭头键,并且箭头方向的子弹从屏幕中间出来。我有四张我在油漆中创建的子弹图像,并使用这两个类:

这是创建和组织项目符号的类:

public class BulletAnimator extends JPanel implements ActionListener
{
  int startX,startY;
  boolean yAxis = false;
  boolean xAxis = false;
  Timer animator;
  String direction;


  public BulletAnimator(int sX, int sY, String d)
  {
    direction = d;

    startX = sX;
    startY = sY;

    animator = new Timer (10, this);
    animator.start();
  }

  //chooses the right picture for the right direction
  public ImageIcon chooseBulletPicture ()
  {
    String path = "bullet";

    if (direction.equals("left"))
      path += "LEFT";
    else if (direction.equals ("right"))
      path += "RIGHT";
    else if (direction.equals ("up"))
      path += "UP";
    else
      path += "DOWN";

    path += ".png";

    ImageIcon b= new ImageIcon (path);

    return b;
  }

  public void paintComponent (Graphics g)
  {
    super. paintComponent(g);

    if (startX >= 500 || startY >= 500)
      animator.stop();

    if (direction.equals ("up"))
      startY -=2;
    else if (direction.equals ("down"))
      startY +=2;
    else if (direction.equals ("right"))
      startX += 2;
    else
      startX -=2;


    chooseBulletPicture().paintIcon (this, g, startX, startY);
   }

  public void actionPerformed(ActionEvent e)
  {
    repaint ();
  }
}

这是类添加keyListeners并测试它:

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

public class Test extends JFrame implements KeyListener
{
  JFrame f;

  public Test ()
  {
    addKeyListener (this);
    setFocusable (true);

    f = new JFrame ();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setVisible(true);
    f.setSize(500, 500);
  }

  public void keyPressed(KeyEvent e) 
  {
    BulletAnimator s = new BulletAnimator (250, 250, "initialized---blank");

    //creates bullet w/ correct direction
    if (e.getKeyCode() == KeyEvent.VK_RIGHT )
    {
      s = new BulletAnimator (250, 250, "right");
    } 
    else if (e.getKeyCode() == KeyEvent.VK_LEFT ) 
    {
       s = new BulletAnimator (250, 250, "left"); 
    } 
    else if (e.getKeyCode() == KeyEvent.VK_UP ) 
    {
       s = new BulletAnimator (250, 250, "up");
    } 
    else if (e.getKeyCode() == KeyEvent.VK_DOWN )
    {
       s = new BulletAnimator (250, 250, "down");
    }

    System.out.println ("keyPressed method read");//checks if keyPressed method was looked at

    f.add (s);
    repaint();
  }

  public void keyReleased (KeyEvent e)
  {}
  public void keyTyped (KeyEvent e)
  {}

  public static void main (String [] args)
  {
    Test t = new Test ();
  }
}

正如你所看到的,我试图进行一项测试,说" keyPressed方法读取" ...当程序运行时它不会打印。实际上什么都没有发生它只是一个灰色的屏幕......真的很令人沮丧。如果你花时间看它,那么提前谢谢你,我非常感谢任何建议!

2 个答案:

答案 0 :(得分:4)

同样,不要使用KeyListeners,使用键绑定,这将允许您在应用程序范围内监听键击,而不必担心焦点和更高的抽象级别(使用起来也更安全)。

例如:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.*;

public class Test2 extends JPanel {
   private static final int PREF_W = 400;
   private static final int PREF_H = PREF_W;
   private static final int TIMER_DELAY = 50;
   private Timer leftKeyTimer = new Timer(TIMER_DELAY , new TimerListener());


   public Test2() {
      int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
      InputMap inputMap = getInputMap(condition );
      ActionMap actionMap = getActionMap();

      String leftDownKey = "Left Down";
      String leftUpKey = "Left Up";
      KeyStroke leftDown = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT , 0, false);
      KeyStroke leftUp = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT , 0, true);
      inputMap.put(leftDown, leftDownKey);
      inputMap.put(leftUp, leftUpKey);

      actionMap.put(leftDownKey, new LeftKeyAction(false));
      actionMap.put(leftUpKey, new LeftKeyAction(true));
      leftKeyTimer.setActionCommand("Left Key");
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

   private class LeftKeyAction extends AbstractAction {
      private boolean onKeyRelease;

      public LeftKeyAction(boolean onKeyRelease) {
         this.onKeyRelease = onKeyRelease;
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         if (onKeyRelease) {
            if (leftKeyTimer != null && leftKeyTimer.isRunning()) {
               leftKeyTimer.stop();
            }
         } else {
            if (leftKeyTimer != null && !leftKeyTimer.isRunning()) {
               leftKeyTimer.start();
            }

         }
      }
   }

   private class TimerListener implements ActionListener {
      public void actionPerformed(ActionEvent actEvt) {
         System.out.println(actEvt.getActionCommand());
      }
   }

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

      JFrame frame = new JFrame("Test2");
      frame.setDefaultCloseOperation(JFrame.EXIT_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();
         }
      });
   }
}

答案 1 :(得分:2)

您正在扩展JFrame类,以便new Test()正在创建JFrame的(扩展)实例,然后您将KeyListener添加到此实例。但是,您可见的框架是您在Test()构造函数中通过

创建的框架
f = new JFrame ();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
f.setSize(500, 500);

您没有将KeyListener添加到此JFrame实例中。因此,KeyListener只会在Test实例可见并且处于焦点时才会响应。

我建议这样做:

public class Test extends JFrame implements KeyListener {
  JFrame f; // Remove this.

  public Test () {
    super();
    addKeyListener (this);
    setFocusable (true);

    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    setSize(500, 500);
  }
}

要绘制图标,您还需要修改BulletAnimator代码:

public void actionPerformed( ActionEvent e ) {
  repaint();
  revalidate();  // new line
}

并在f.add(s)方法中将add(s)更改为keyPressed,以将图标添加到测试框架。

免责声明:正如其他人所指出的那样,有更好的解决方案来处理按键。我上面的建议仅确定了上面发布的原始代码的问题。