Scott Field
Scott Field

Reputation: 35

Why does my Java key input work only sometimes?

I've been trying to add some key input to my code for a while now, but for some reason it won't work in one class but in another it works just fine and I don't know why. An Example Here Is the one that DOES work.

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.KeyStroke;
public class KeyStrokeSample {
  public static void main(String[] a) {
  String ACTION_KEY = "theAction";
  JFrame frame = new JFrame("KeyStroke Sample");
  frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  JButton buttonA = new JButton("Press 'W'");

      Action actionListener = new AbstractAction() {
        public void actionPerformed(ActionEvent actionEvent) {
          JButton source = (JButton) actionEvent.getSource();
            System.out.println(source.getText());

  }
};
KeyStroke W = KeyStroke.getKeyStroke("W");
InputMap inputMap = buttonA.getInputMap();
inputMap.put(W, ACTION_KEY);
ActionMap actionMap = buttonA.getActionMap();
actionMap.put(ACTION_KEY, actionListener);
frame.add(buttonA);
frame.setSize(400, 200);
frame.setVisible(true);
}
}

However when I tried to put it into my Sprite class and get the same response NOTHING HAPPENED I've tried changing the order and every time I don't get a response even though their is no error message. The code for that particular problem is below in my main method

 public static void main(String[] args) throws IOException, 
 InterruptedException{

//setting the window and sprites
Sprite orig_world = new Sprite(ImageIO.read(new 
File("C:/Users/sfiel42/Documents/game/castles.png")),0,0);
Sprite world      = new Sprite(ImageIO.read(new 
File("C:/Users/sfiel42/Documents/game/castles.png")),0,0);

JLabel label      = new JLabel(); 
label.setLocation(0,0);
label.setIcon(new ImageIcon(world.getSprite()));
label.setVisible(true);   

JFrame frame      = new JFrame();
frame.setVisible(true);
frame.setSize(783,615);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(label);


Sprite archer = new Sprite(ImageIO.read(new 
File("C:/Users/sfiel42/Documents/game/archer.png")),30,40);

String ACTION_KEY = "theAction";
JButton buttonA = new JButton("Button For W");
Action actionListener = new AbstractAction() {
  public void actionPerformed(ActionEvent actionEvent) {
    JButton source = (JButton) actionEvent.getSource();
    System.out.println(source.getText());
  }
};
KeyStroke W = KeyStroke.getKeyStroke("W");
InputMap inputMap = buttonA.getInputMap();
inputMap.put(W, ACTION_KEY);
ActionMap actionMap = buttonA.getActionMap();
actionMap.put(ACTION_KEY, actionListener);
buttonA.setVisible(false);
frame.add(buttonA);

If you want the rest of the sprite class to help figure out what the problem is the whole thing can be found at the link to my other question. Why can't I erase my Sprite

Upvotes: 1

Views: 376

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347214

Part of your problem is focus related issue.

When you use getInputMap(), you asking for the InputMap which responds to key events only when the component has keyboard focus.

Instead, consider using JComponent#getInputMap(int) and pass it one of the other conditions, like JComponent#WHEN_IN_FOCUSED_WINDOW

Additional, instead of registering the key bindings against the buttons, I'd bind them to the parent component and re-use Action with the buttons

public class MoveAction extends AbstractAction {
    public MoveAction(String name) {
        putValue(NAME, name);
    }

    public void actionPerformed(ActionEvent actionEvent) {
        System.out.println(getValue(NAME));
    }
}

//...

MoveAction action = new MoveAction("W");
String ACTION_KEY = "theAction";
KeyStroke W = KeyStroke.getKeyStroke(KeyEvent.VK_W, 0);
InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
inputMap.put(W, ACTION_KEY);
ActionMap actionMap = getActionMap();
actionMap.put(ACTION_KEY, action);

JButton buttonA = new JButton(action);
buttonA.setVisible(false); // This worries me :P

Using an Action this way produces a much more flexible and re-usable solution

I'd also avoid using things like KeyStroke.getKeyStroke("W"), because this will probably return a KeyStroke for SHIFT+W which probably isn't what you want. Instead make use KeyStroke.getKeyStroke(int, int) which will give you much more control over it

Upvotes: 1

Related Questions