Почему мой ввод с клавиши Java работает только иногда?

Я уже некоторое время пытаюсь добавить ключевой ввод в свой код, но по какой-то причине он не будет работать в одном классе, но в другом он работает просто отлично, и я не знаю, почему. Пример Вот тот, который ДЕЙСТВИТЕЛЬНО работает.

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);
}
}

Однако, когда я попытался поместить его в свой класс Sprite и получить тот же ответ, НИЧЕГО НЕ ПРОИЗОШЛО, я пытался изменить порядок, и каждый раз я не получаю ответа, даже если это не сообщение об ошибке. Код для этой конкретной проблемы приведен ниже в моем основном методе.

 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);

Если вы хотите, чтобы остальная часть класса спрайтов помогла выяснить, в чем проблема, все это можно найти по ссылке на мой другой вопрос. Почему я не могу стереть свой Sprite


person Scott Field    schedule 14.05.2017    source источник


Ответы (1)


Часть вашей проблемы связана с фокусом.

Когда вы используете getInputMap(), вы запрашиваете InputMap, который отвечает на ключевые события только тогда, когда компонент имеет фокус клавиатуры.

Вместо этого рассмотрите возможность использования JComponent#getInputMap(int) и передайте ему одно из других условий, например JComponent#WHEN_IN_FOCUSED_WINDOW

Кроме того, вместо того, чтобы регистрировать привязки клавиш к кнопкам, я бы привязал их к родительскому компоненту и повторно использовал Action с кнопками.

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

Использование Action таким образом дает гораздо более гибкое и повторно используемое решение.

Я бы также избегал использования таких вещей, как KeyStroke.getKeyStroke("W"), потому что это, вероятно, вернет KeyStroke для SHIFT+W, что, вероятно, не то, что вам нужно. Вместо этого используйте KeyStroke.getKeyStroke(int, int) что даст вам гораздо больший контроль над ним

person MadProgrammer    schedule 14.05.2017
comment
Ну, это помогает, но я надеялся, что смогу регистрировать нажатия клавиш в основном методе моего класса Sprite. Могу ли я как-нибудь это сделать? - person Scott Field; 15.05.2017
comment
Привязки клавиш должны быть зарегистрированы для компонента, который активен/будет активен на экране. - person MadProgrammer; 15.05.2017