java - KeyListener 可以工作,但不能

标签 java swing keyboard keylistener japplet

我对按键监听器很陌生,但最近我做了一个小程序,如下所示,它使用按键监听器使 A、W、S、D 键移动一个正方形。好吧,我使用 dropbox 在这台笔记本电脑上获取该程序,但现在它不起作用。我觉得很奇怪,它可以在键盘上工作,但不能在笔记本电脑键盘上工作。有什么想法吗?这是代码,以及一部分:

   public class Game extends JApplet implements KeyListener
{
    public boolean isMoving = false;
    int test = 0;
    Rect r = new Rect();
            public void keyPressed(KeyEvent e){}
            public void keyReleased(KeyEvent e){} // ignore
            public void keyTyped(KeyEvent e)
            {
                char keyChar = e.getKeyChar();
                if (keyChar == KeyEvent.VK_S)
                    {
                        r.yVelocity -= 1;
                    }
                if (keyChar == KeyEvent.VK_W)
                    {
                        r.yVelocity+=1;
                    }
                if (keyChar == KeyEvent.VK_A)
                    {
                        r.xVelocity -=1;
                    }
                if (keyChar == KeyEvent.VK_D)
                    {
                        r.xVelocity +=1;
                    }
            }

最佳答案

KeyListener 存在焦点问题。也就是说,它只会在可聚焦且具有焦点时响应关键事件。

简单的解决方案是使注册了KeyListener的组件可聚焦并使用requestFocusInWindow,但这并不能保证该组件将获得键盘焦点.

更好的解决方案是使用 Key Bindings API 允许您配置引发关键事件所需的焦点级别...

更新了键绑定(bind)示例/测试

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.util.ArrayList;
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.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestKeyBindings {

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

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

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

    public class KeyPane extends JPanel {

        private Triangle up;
        private Triangle down;
        private Triangle left;
        private Triangle right;

        private Set<String> activeKeys;

        public KeyPane() {
            activeKeys = new HashSet<>(4);

            up = new Triangle(20);
            down = new Triangle(20);
            left = new Triangle(20);
            right = new Triangle(20);

            AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(-90), 10, 10);
            left.transform(at);
            at = AffineTransform.getRotateInstance(Math.toRadians(180), 10, 10);
            down.transform(at);
            at = AffineTransform.getRotateInstance(Math.toRadians(-270), 10, 10);
            right.transform(at);

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upPressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downPressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "leftPressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "rightPressed");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upReleased");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downReleased");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "leftReleased");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "rightReleased");

            ActionMap am = getActionMap();
            am.put("upPressed", new DirectionAction("up", true));
            am.put("downPressed", new DirectionAction("down", true));
            am.put("leftPressed", new DirectionAction("left", true));
            am.put("rightPressed", new DirectionAction("right", true));
            am.put("upReleased", new DirectionAction("up", false));
            am.put("downReleased", new DirectionAction("down", false));
            am.put("leftReleased", new DirectionAction("left", false));
            am.put("rightReleased", new DirectionAction("right", false));
        }

        public void addKey(String name) {
            activeKeys.add(name);
            repaint();
        }

        public void removeKey(String name) {
            activeKeys.remove(name);
            repaint();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int x = (getWidth() - (up.getBounds().width * 3)) / 2;
            int y = (getHeight() - 10) / 2;

            AffineTransform at = AffineTransform.getTranslateInstance(x, y);
            if (activeKeys.contains("left")) {
                g2d.fill(left.createTransformedShape(at));
            } else {
                g2d.draw(left.createTransformedShape(at));
            }
            at = AffineTransform.getTranslateInstance(x + 40, y);
            if (activeKeys.contains("right")) {
                g2d.fill(right.createTransformedShape(at));
            } else {
                g2d.draw(right.createTransformedShape(at));
            }
            at = AffineTransform.getTranslateInstance(x + 20, y - 20);
            if (activeKeys.contains("up")) {
                g2d.fill(up.createTransformedShape(at));
            } else {
                g2d.draw(up.createTransformedShape(at));
            }
            at = AffineTransform.getTranslateInstance(x + 20, y + 20);
            if (activeKeys.contains("down")) {
                g2d.fill(down.createTransformedShape(at));
            } else {
                g2d.draw(down.createTransformedShape(at));
            }

            g2d.dispose();
        }

        public class DirectionAction extends AbstractAction {

            private String name;
            private boolean pressed;

            public DirectionAction(String name, boolean pressed) {
                this.name = name;
                this.pressed = pressed;
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                if (pressed) {
                    addKey(name);
                } else {
                    removeKey(name);
                }
            }

        }
    }

    public class Triangle extends Path2D.Double {

        public Triangle(int size) {

            moveTo(size / 2, 0);
            lineTo(size, size);
            lineTo(0, size);
            closePath();

        }

    }

}

关于java - KeyListener 可以工作,但不能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22677699/

相关文章:

java - 如何更新我的 Java 程序以仅显示两位小数

c - 在无限循环中显示相同的字符

java - 如何获取JRadioButton的ButtonGroup

java - 将 JComboBox 与 ItemListener/ActionListener 结合使用

IOS - 触摸 UIPickerView 时关闭键盘

java - 具有泛型的订阅模型 - 实现多个泛型接口(interface)

java - 有没有一种简单的方法可以知道当前是否显示模式对话框?

java - Android - setBackgroundColor int 值太大?

java - 在 Android JNI/NDK 代码中从 C++ 函数调用 C 函数

JAVA Trivia 游戏数组超出范围