Использование привязок клавиш с клавишами со стрелками

Я создаю игру, которая использует клавиши со стрелками для перемещения спрайта. Я добавил привязки клавиш для клавиш со стрелками и буквы n, но клавиши со стрелками не работают. Вот мой код:

public class MyPanel extends JPanel {

    Sprite sprite = new Sprite();

    Timer gameClock = new Timer(DELAY, new ActionListener(){
        public void actionPerformed(ActionEvent e){
            sprite.move();
            // omit other methods
        }
    });

    // omit other member variables

    public MyPanel(){
        Abstract Action newGameAction = new AbstractAction("new game") {

            public void actionPerformed(ActionEvent e){
                doNewGame();
            }
        }

        setFocusable(true);

        addKeyBinding(new Pair<String, Action>("N", newGameAction));
        ArrayList<Pair<String, Action>> pairs = sprite.findKeyBindingPairs();
        for (Pair<String, Action> p : pairs)
            addKeyBindings(p);


        gameClock.start();

        // omit other panel init

    }

    private void addKeyBindings(Pair<String, Action> pair) {
        String key = pair.getFirstElement();
        Action action = pair.getSecondElement();
        String desc = action.getValue(AbstractAction.NAME).toString();
        getInputMap().put(KeyStroke.getKeyStroke(key), desc);
        getActionMap().put(desc, action);
    }

    // omit other methods
}


public class Sprite {

    private class ChangeDirAction extends AbstractAction {
        int dx, dy;

        ChangeDirAction(String name, int dx, int dy){
            super(name);
            this.dx = dx;
            this.dy = dy;
        }

        public void actionPerformed(ActionEvent e){
            setVelocity(dx, dy);
        }
    }

    private int dx_, dy_;
    Point pos;

    // omit other instance variables

    public void move(){
        // With printlns dx_ and dy_ are both 0 here. Why?
        Point newPos = new Point(pos);
        newPos.translate(dx_, dy_);

        // omit code to test whether newPos is valid

        if (isWall(newPos) || isOutsidePanel(newPos))
            setVelocity(0, 0);
        else
            pos = newPos;
    }


    private void setVelocity(int dx, int dy){
        dx_ = dx;
        dy_ = dy;
        // With printlns dx_ and dy_ change when arrow keys are pressed
    }

    public ArrayList<Pair<String, Action>> findKeyBindingPairs(){
        Pair<String, Action> leftPair = new Pair<String, Action>("LEFT", new ChangeDirAction("left", -1, 0));
        Pair<String, Action> rightPair = new Pair<String, Action>("RIGHT", new ChangeDirAction("right", 1, 0));
        Pair<String, Action> upPair = new Pair<String, Action>("UP", new ChangeDirAction("up", 0, -1));
        Pair<String, Action> downPair = new Pair<String, Action>("DOWN", new ChangeDirAction("down", 0, 1));
        ArrayList<Pair<String, Action>> result = new ArrayList<Pair<String, Action>>();
        result.add(leftPair);
        result.add(rightPair);
        result.add(upPair);
        result.add(downPair);
        return result;
    }

    // omit other methods

}

person Eva    schedule 22.09.2011    source источник
comment
Я понял это, пытаясь сделать SSCCE. Когда я начинаю новую игру, я создаю новый объект Sprite без привязок клавиш старого, поэтому данные привязки клавиш теряются. Я переместил свой код, чтобы добавить привязки клавиш к методу doNewGame(), и теперь он работает.   -  person Eva    schedule 22.09.2011
comment
это одна из причин, по которой SSCCE так настоятельно рекомендуется :-) Кстати, вы можете сами добавить ответ на свой вопрос и принять его.   -  person kleopatra    schedule 22.09.2011


Ответы (2)


Я понял это, пытаясь сделать SSCCE. Когда я начинаю новую игру, я создаю новый объект Sprite без привязок клавиш старого, поэтому данные привязки клавиш теряются. Я переместил свой код, чтобы добавить привязки клавиш к методу doNewGame(), и теперь он работает.

person Eva    schedule 22.09.2011

Не называйте свой собственный класс "Панель". Существует класс AWT под названием «Панель», поэтому ваш код сбивает с толку. Используйте более описательное имя.

InputMap по умолчанию используется для обработки привязок клавиш, когда компонент находится в фокусе. Я предполагаю, что вам нужно добавить:

setFocusable( true );

в конструкторе вашего класса.

person camickr    schedule 22.09.2011
comment
setFocusable() находится в моем конструкторе. Клавиши со стрелками по-прежнему не работают, а буква n работает нормально. - person Eva; 22.09.2011
comment
Код, который вы разместили, не показывает этого и не показывает, как вы создали привязку N. Опубликуйте SSCCE, демонстрирующий проблему. - person camickr; 22.09.2011