Home > Mobile >  What am I doing wrong with this keybind
What am I doing wrong with this keybind

Time:03-24

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 dont know why, but this program says that get inputMap and getActionMap dont exist. which is weird i could have sworn i put it all in correctly . i followed a tutorial even but nothing seems to work.

CodePudding user response:

I prefer not to use KeyStroke.getKeyStroke as there is a level of ambiguity in how the key stroke might be triggered, this is a personal thing, but I've wasted too much time trying to debug issues related to it.

Instead, I prefer to use KeyStroke.getKeyStroke(KeyEvent.VK_W, 0) instead. This is much easier to (for me) to understand and I can configure "pressed" or "released" functionality through it as well.

The default behaviour of getInputMap() is to generate events WHEN_FOCUSED, this is the same as you would expect from KeyListener, but you're adding your key binding to the JFrame, which is unlikely to ever gain focus (it's a composite component, so it doesn't make sense for it to do so).

Instead, you should try something like...

frame.getInputMap(WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "escapePressed");
frame.getActionMap().put("escapePressed", escapePressed);

Now, personally, I think this kind of thing is probably better maintained via a component, which gets added to the frame, but this is me.

CodePudding user response:

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.

  • Related