Search code examples
javaswingkey-bindings

What am I doing wrong with this key binding?


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

class Menu{

  JFrame frame = new JFrame();
  Image icon = Toolkit.getDefaultToolkit().getImage("image1.png");
  Action escapePressed;
  
  public Menu() {
    frame.setVisible(true);
    frame.setIconImage(icon);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setMinimumSize(new Dimension(500, 500));
    frame.setTitle("Nine Games");
    frame.setFocusable(true);
    frame.setResizable(true);
    frame.add(new StartScreen());

    escapePressed = new EscapePressed();

    frame.getInputMap().put(KeyStroke.getKeyStroke('w'), "escapePressed");
    frame.getActionMap().put("escapePressed", escapePressed);
  }

  public class EscapePressed extends AbstractAction {
    @Override
    public void actionPerformed(ActionEvent e) {
      System.out.println("Escape Pressed");
      System.exit(0);
    }
  }
}

I don't know why, but this program says that getInputMap and getActionMap don't exist. Which is weird. I could have sworn I put it all in correctly . I followed a tutorial even but nothing seems to work.


Solution

  • A couple of problems:

    1. a JFrame doesn't have an InputMap and ActionMap. Only components that extend from JComponent can use Key Bindings. So to handle an exit KeyStroke you probably want to use the JRootPane to add your bindings
    2. you don't want to use the default WHEN_FOCUSED InputMap because the root pane won't have focus as some other component you add to the frame will have focus. Instead you want to use the WHEN_IN_FOCUSED_WINDOW InputMap.

    So your code might be like:

    //frame.getInputMap().put(KeyStroke.getKeyStroke('w'), "escapePressed");
    //frame.getActionMap().put("escapePressed", escapePressed);    
    frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke('w'), "escapePressed");
    frame.getRootPane().getActionMap().put("escapePressed", escapePressed);
    

    Read the section from the Swing tutorial on How to Use Key Bindings for more information.

    Also check out Using Top Level Containers for more information about the root pane.