Java KeyBindings перестают работать через несколько секунд - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь перейти от Java KeyListeners к KeyBindings для анимации, но они работают в течение нескольких секунд, а затем полностью останавливаются.Я печатаю сообщения на консоли, когда действия запускаются, и эти сообщения останавливаются, поэтому не только рисование не работает, но и срабатывание действий при нажатии клавиш.

Мой классрасширяет JFrame, и я просто добавляю JPanel к нему и добавляю JLabel к JPanel.Я использую флаги, переключаемые действиями, чтобы указать, как JLabel должен двигаться, и я использую метод JFrame actionPerformed, чтобы проверить состояние флагов и отрегулировать местоположение JLabel.

Я пытался добавить JComponent.WHEN_IN_FOCUSED_WINDOW внутри getInputMap метода, но это не имело значения.

Вот код:

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;

public class KeyBindingTest extends JFrame implements ActionListener {

    long counter = 0;
    int speed = 5;
    boolean isUp = false, isDown = false, isLeft = false, isRight = false;
    JLabel j = new JLabel();
    JPanel p = new JPanel();
    Timer t;

    Action upPressed = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("up on");
            isUp = true;
        }
    };
    Action upReleased = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            isUp = false;
            System.out.println("up off");
        }
    };
    Action downPressed = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("down on");
            isDown = true;
        }
    };
    Action downReleased = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("down off");
            isDown = false;
        }
    };
    Action leftPressed = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("left on");
            isLeft = true;
        }
    };
    Action leftReleased = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("left off");
            isLeft = false;
        }
    };
    Action rightPressed = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("right on");
            isRight = true;
        }
    };
    Action rightReleased = new AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("right off");
            isRight = false;
        }
    };

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                // The try/catch block prevents errors from crashing the program
                try {
                    KeyBindingTest window = new KeyBindingTest(); // Create and setup the main game window
                    window.run(); // show the new window
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private void run() {
        this.setBounds(640, 400, 640, 400);
        this.setVisible(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        p.setBounds(0, 0, this.getWidth(), this.getHeight());
        p.setVisible(true);
        p.setBackground(Color.blue);
        p.setOpaque(true);
        p.setFocusable(true);
        p.setLayout(null);
        j.setBounds(320, 200, 10, 10);
        j.setVisible(true);
        j.setBackground(Color.red);
        j.setOpaque(true);
        this.add(p);
        p.add(j);
        p.requestFocusInWindow();
        setupKeyBindings();
        t = new Timer(1000 / 40, this);
        t.start();
    }

    private void setupKeyBindings() {
        p.getInputMap().put(KeyStroke.getKeyStroke("W"), "moveUp");
        p.getActionMap().put("moveUp", upPressed);
        p.getInputMap().put(KeyStroke.getKeyStroke("released W"), "stopUp");
        p.getActionMap().put("stopUp", upReleased);
        p.getInputMap().put(KeyStroke.getKeyStroke("S"), "moveDown");
        p.getActionMap().put("moveDown", downPressed);
        p.getInputMap().put(KeyStroke.getKeyStroke("released S"), "stopDown");
        p.getActionMap().put("stopDown", downReleased);
        p.getInputMap().put(KeyStroke.getKeyStroke("A"), "moveLeft");
        p.getActionMap().put("moveLeft", leftPressed);
        p.getInputMap().put(KeyStroke.getKeyStroke("released A"), "stopLeft");
        p.getActionMap().put("stopLeft", leftReleased);
        p.getInputMap().put(KeyStroke.getKeyStroke("D"), "moveRight");
        p.getActionMap().put("moveRight", rightPressed);
        p.getInputMap().put(KeyStroke.getKeyStroke("released D"), "stopRight");
        p.getActionMap().put("stopRight", rightReleased);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        counter++;
        System.out.println(counter);
        if (isUp) {
            j.setLocation(j.getX(), j.getY() - speed);
        }
        if (isDown) {
            j.setLocation(j.getX(), j.getY() + speed);
        }
        if (isLeft) {
            j.setLocation(j.getX() - speed, j.getY());
        }
        if (isRight) {
            j.setLocation(j.getX() + speed, j.getY());
        }
        repaint();
    }

}

1 Ответ

0 голосов
/ 30 мая 2018

Это личное дело, но у вас, как правило, будет меньше проблем, если вы будете использовать что-то вроде KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false) сверх KeyStroke.getKeyStroke("W")

Эквивалентом KeyStroke.getKeyStroke("released W") будет KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true) Я вернулсяи далее через ваш пример я попытался заменить KeyStroke.getKeyStroke("W") на KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false) и его эквиваленты;Я попытался заменить флаги boolean на Set, и у меня все еще остается та же проблема

. Затем я пошел и выбросил ваш код и начал новый проект.Сначала я попробовал собственный маршрут рисования, и это сработало нормально.Затем я попробовал маршрут на основе компонентов, и это сработало ... 101

Итак, хотя у меня до сих пор нет «ответа» на вопрос, почему он не работает, у меня есть пример, который делает ...

Пример

И поскольку я действительно проверил свои предложения ...

import com.sun.glass.events.KeyEvent;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public enum Input {
        UP, DOWN, LEFT, RIGHT
    }

    public class TestPane extends JPanel {

        private Set<Input> inputs = new HashSet<>();

        private int delta = 4;

        private JLabel label;

        public TestPane() {
            InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap actionMap = getActionMap();

            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "Up.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), "Up.relesed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "Down.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), "Down.relesed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false), "Left.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, true), "Left.relesed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, false), "Right.pressed");
            inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0, true), "Right.relesed");

            actionMap.put("Up.pressed", new InputAction(Input.UP, true));
            actionMap.put("Up.relesed", new InputAction(Input.UP, false));
            actionMap.put("Down.pressed", new InputAction(Input.DOWN, true));
            actionMap.put("Down.relesed", new InputAction(Input.DOWN, false));
            actionMap.put("Left.pressed", new InputAction(Input.LEFT, true));
            actionMap.put("Left.relesed", new InputAction(Input.LEFT, false));
            actionMap.put("Right.pressed", new InputAction(Input.RIGHT, true));
            actionMap.put("Right.relesed", new InputAction(Input.RIGHT, false));

            setLayout(null);
            label = new JLabel();
            label.setBackground(Color.RED);
            label.setOpaque(true);
            label.setBounds(0, 0, 10, 10);
            add(label);

            Timer timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    int xPos = label.getX();
                    int yPos = label.getY();
                    if (inputs.contains(Input.UP)) {
                        yPos -= delta;
                    }
                    if (inputs.contains(Input.DOWN)) {
                        yPos += delta;
                    }
                    if (inputs.contains(Input.LEFT)) {
                        xPos -= delta;
                    }
                    if (inputs.contains(Input.RIGHT)) {
                        xPos += delta;
                    }

                    if (xPos < 0) {
                        xPos = 0;
                    } else if (xPos + 10 > getWidth()) {
                        xPos = getWidth() - 10;
                    }
                    if (yPos < 0) {
                        yPos = 0;
                    } else if (yPos + 10 > getHeight()) {
                        yPos = getHeight() - 10;
                    }
                    label.setLocation(xPos, yPos);
                    repaint();
                }
            });
            timer.start();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

//        protected void paintComponent(Graphics g) {
//            super.paintComponent(g);
//            Graphics2D g2d = (Graphics2D) g.create();
//            g2d.setColor(Color.RED);
//            g2d.drawRect(xPos, yPos, 10, 10);
//            g2d.dispose();
//        }

        public class InputAction extends AbstractAction {
            private Input input;
            private boolean pressed;

            public InputAction(Input input, boolean pressed) {
                this.input = input;
                this.pressed = pressed;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                if (pressed) {
                    inputs.add(input);
                } else {
                    inputs.remove(input);
                }
            }
        }
    }

}

Примечание ...

Этот "тип" вопросаВ последнее время меня часто спрашивают, я предполагаю, что это какое-то классовое задание, так как мы видели несколько вариантов этого стиля кода.Как мы неоднократно советовали, использование компонентов таким способом не рекомендуется, поскольку они не предназначены для такого рода вещей.Вы получите лучшие (и более легкие) результаты, используя собственный маршрут рисования, как показано в Перемещение JLabel с помощью ключевых ставок

...