How do you make key bindings for a java.awt.Frame?

2019-01-28 09:11发布

问题:

Background

My window is a java.awt.Frame, and inside of the Frame are two Panels (java.awt.Panel). I'm trying to make it so that the window handles buttons I press.

Try Number 1

I tried using a KeyListener, making the Frame implement the KeyListener. I added the KeyListener to the Frame, but the KeyListener functions didn't do anything when I pressed keys. (I tried printing with System.out.println().)

Try Number 2

I tried following this tutorial: http://tips4java.wordpress.com/2008/10/10/key-bindings/ . Here is the my attempt to handle pressing the SPACEBAR:

public void registerActions(){                                  //01
  Action myAction = new AbstractAction(){                       //02
    @Override                                                   //03
    public void actionPerformed(ActionEvent e) {                //04
      System.out.println("GREAT SUCCESS!");                     //05
    }                                                           //06
  };                                                            //07
  KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0); //08
  component.getInputMap().put(key, "myAction");                 //09
  component.getActionMap().put("myAction", myAction);           //10
}                                                               //11

The main problem is that I don't know what 'component' should be in lines 09 & 10, because my application does not have any JComponents.

My Question

Is there a way to do this without using swing components? Or is there another way to handle key presses?

回答1:

I found that I could do this with an AWTEventListener.

public class MyFrame extends Frame implements AWTEventListener {

  ...

  public MyFrame(String title){
    super(title);
    ...
    this.getToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
  }

  @Override
  public void eventDispatched(AWTEvent event) {
    if(event instanceof KeyEvent){
      KeyEvent key = (KeyEvent)event;
      if(key.getID()==KeyEvent.KEY_PRESSED){ //Handle key presses
        System.out.println(key.getKeyChar());
        //TODO: do something with the key press
        key.consume();
      }
    }
  }
}


回答2:

Okay, here's an example using a JPanel.

I created a Frame, set it's layout to BorderLayout added to the KeyPane to it and voila...

public class KeyPane extends JPanel {

    private Timer paintTimer;
    private MouseFocusHandler mouseFocusHandler;

    private boolean spaceOn = false;
    private int yPos = 0;
    private int direction = 2;

    private Rectangle blob = new Rectangle(0, 0, 10, 10);

    public KeyPane() {

        setFocusable(true);

        InputMap im = getInputMap(WHEN_FOCUSED);
        ActionMap am = getActionMap();

        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "Space");
        am.put("Space", new SpaceAction());

        setPreferredSize(new Dimension(100, 100));

        getPaintTimer().setCoalesce(false);
        getPaintTimer().start();

    }

    @Override
    public void addNotify() {
        super.addNotify();
        requestFocusInWindow();
        addMouseListener(getMouseFocusHandler());
        getPaintTimer().start();
    }

    @Override
    public void removeNotify() {
        removeMouseListener(getMouseFocusHandler());
        getPaintTimer().stop();
        super.removeNotify();
    }

    protected Timer getPaintTimer() {
        if (paintTimer == null) {
            paintTimer = new Timer(40, new RepaintAction());
            paintTimer.setRepeats(true);
            paintTimer.setCoalesce(true);
        }
        return paintTimer;
    }

    protected MouseFocusHandler getMouseFocusHandler() {
        if (mouseFocusHandler == null) {
            mouseFocusHandler = new MouseFocusHandler();
        }
        return mouseFocusHandler;
    }

    @Override
    protected void paintComponent(Graphics g) {

        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();

        int width = getWidth() - 1;
        int height = getHeight() - 1;

        g2d.setColor(Color.GREEN);

        blob.x = (width - blob.width) / 2;

        System.out.println(blob);
        g2d.fill(blob);

        if (spaceOn) {
            g2d.setFont(UIManager.getFont("Label.font").deriveFont(24f));
            FontMetrics fm = g2d.getFontMetrics();

            String spaceIsOn = "Space On";

            int x = (width - fm.stringWidth(spaceIsOn)) / 2;
            int y = ((height - fm.getHeight()) / 2) + fm.getAscent();

            g2d.drawString(spaceIsOn, x, y);
        }

        g2d.dispose();

    }

    protected class MouseFocusHandler extends MouseAdapter {

        @Override
        public void mouseClicked(MouseEvent e) {
            requestFocusInWindow();
        }

    }

    protected class RepaintAction implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            yPos += direction;
            blob.y = yPos;

            if (blob.y + blob.height > getHeight() - 1) {
                blob.y = getHeight() - 1 - blob.height;
                direction = -2;
            } else if (blob.y < 0) {
                blob.y = 0;
                direction = 2;
            }
            repaint();
        }

    }

    protected class SpaceAction extends AbstractAction {

        @Override
        public void actionPerformed(ActionEvent e) {
            spaceOn = !spaceOn;
            repaint();
        }

    }

}