首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java KeyBindings在几秒钟后停止工作。

Java KeyBindings在几秒钟后停止工作。
EN

Stack Overflow用户
提问于 2018-05-30 14:59:45
回答 1查看 55关注 0票数 1

我正试着从Java KeyListeners转到KeyBindings来做动画,但它们只工作了几秒钟,然后就完全停止了。当操作触发时,我会将消息打印到控制台,而这些消息会停止,所以不只是绘图不起作用,而是在按下按键时触发了操作。

我的类扩展了JFrame,我只是向它添加了一个JPanel,并向JPanel添加了一个JLabel。我使用由操作切换的标志来指示JLabel应该如何移动,并使用JFrame的actionPerformed方法来检查标志的状态并调整JLabel的位置。

我尝试过在getInputMap方法中添加JComponent.WHEN_IN_FOCUSED_WINDOW,但没有什么不同。

代码如下:

代码语言:javascript
复制
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();
    }

}
EN

回答 1

Stack Overflow用户

发布于 2018-05-30 15:02:38

这是个人的事情,但是,如果您在KeyStroke.getKeyStroke("W")上使用诸如KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false)之类的东西,您通常会遇到较少的问题

KeyStroke.getKeyStroke("released W")的等价物是KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true)我已经在您的示例中反复尝试,我已经尝试用KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false)和它的等价物替换KeyStroke.getKeyStroke("W");我已经尝试用Set替换boolean标志,但仍然存在相同的问题

然后我扔掉了你的代码,开始了一个新的项目。首先,我尝试了一种自定义的绘画路线,效果很好。然后我尝试了一种基于组件的路由,它起作用了…

所以,虽然我仍然不知道为什么它不能工作,但我有一个例子可以做到……

示例

因为我已经测试过我的建议了。

代码语言:javascript
复制
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);
                }
            }
        }
    }

}

附注:

这种“类型”的问题最近被问得很多,我认为这是某种类型的类分配,因为我们已经看到了这种代码风格的许多变体。正如我们反复建议的那样,以这种方式使用组件是不明智的,它们实际上不是为这种事情而设计的。您将使用自定义绘制路线获得更好(也更容易)的结果,如Make an JLabel move with Key Bidings中所示

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50598222

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档