加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 如何完美地模拟KeyEvents?

发布时间:2020-12-14 14:26:29 所属栏目:Java 来源:网络整理
导读:如何在最终用户键入某些东西时,构建自己的KeyEvent对象,它完美地(或非常接近)匹配从KeyListener接收到的对象? 例如,我有一个英国的ISO键盘布局,并键入“我按下Shift 2的字符.如果我用一个KeyListener在JFrame上记录它,我收到以下事件: java.awt.event.KeyE
如何在最终用户键入某些东西时,构建自己的KeyEvent对象,它完美地(或非常接近)匹配从KeyListener接收到的对象?

例如,我有一个英国的ISO键盘布局,并键入“我按下Shift 2的字符.如果我用一个KeyListener在JFrame上记录它,我收到以下事件:

java.awt.event.KeyEvent[KEY_PRESSED,keyCode=16,keyText=Shift,keyChar=Undefined keyChar,modifiers=Shift,extModifiers=Shift,keyLocation=KEY_LOCATION_LEFT,rawCode=16,primaryLevelUnicode=0,scancode=42,extendedKeyCode=0x10] on frame0
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=50,keyText=2,keyChar='"',keyLocation=KEY_LOCATION_STANDARD,rawCode=50,primaryLevelUnicode=50,scancode=3,extendedKeyCode=0x32] on frame0
java.awt.event.KeyEvent[KEY_TYPED,keyCode=0,keyText=Unknown keyCode: 0x0,keyLocation=KEY_LOCATION_UNKNOWN,rawCode=0,scancode=0,extendedKeyCode=0x0] on frame0
java.awt.event.KeyEvent[KEY_RELEASED,extendedKeyCode=0x10] on frame0
java.awt.event.KeyEvent[KEY_RELEASED,extendedKeyCode=0x32] on frame0

我想创建一个方法,我将给出“作为一个char参数,它将返回一个如上所列的KeyEvents的数组.

我的问题是:

>在KEY_PRESSED和KEY_RELEASED事件中,keyChar =’“’表示被按下的字符(”),但是keyCode = 50表示“非移位”ASCII值(又称为2).我需要知道如何从“字符”中获取这个非移位值.
>对于不同的键盘布局,此非移位值也将不同.例如,美国ANSI布局要求Shift’键入“键,这意味着keyCode将是39而不是50.
>在某些键盘布局上,需要使用Shift键来键入键,但不需要键.例如,#字符需要在美国ANSI键盘上使用Shift 3,但不需要按英国ISO键盘上的移动键.我需要知道是否应该模拟换档按钮/释放事件并提供换档修改器.

任何关于如何解决这些问题的见解将不胜感激.我也应该注意到,在我的情况下使用Robot类不能使用.

解决方法

将虚拟键转换为实际的键序列或再次返回是没有“简单”的方法,至少我没有找到.

调度关键事件的两种主要方式是通过java.awt.Robot或直接通过系统事件队列.你想要使用的将取决于你想要实现什么.

组件通常不能区分从键盘发出的那些你产生你的自我的关键笔划.

下面的例子很复杂,对不起,我发现没有更好的方法来达到我需要的要求.

public class TestKeyEvents {
    public static void main(String[] args) {
        new TestKeyEvents();
    }
    public TestKeyEvents() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                new Thread(new KeyDispatcher()).start();
            }
        });
    }
    public class TestPane extends JPanel {
        public TestPane() {
            setLayout(new BorderLayout());
            JTextArea area = new JTextArea(10,30);
            area.setWrapStyleWord(true);
            area.setLineWrap(true);
            add(area);
        }
    }
    public class KeyDispatcher implements Runnable {
        @Override
        public void run() {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
            }
            dispatchKeyEventsViaEventQueue();
            dispatchKeyEventsViaRobot();
        }

        protected void dispatchKeyEventsViaEventQueue() {
            if (EventQueue.isDispatchThread()) {
                String text = "This is a key sequence dispatched via the event queuen";
                KeySequence keySequence = getKeySequence(text);
                List<KeyEvent> events = new ArrayList<>();
                List<Integer> modifers = new ArrayList<>();
                for (Key key : keySequence) {
                    events.clear();
                    System.out.println(key);
                    switch (key.getStrokeType()) {
                        case Press:
                            switch (key.getKeyCode()) {
                                case KeyEvent.VK_SHIFT:
                                case KeyEvent.VK_ALT:
                                case KeyEvent.VK_CONTROL:
                                case KeyEvent.VK_META:
                                    if (!modifers.contains(key.getKeyCode())) {
                                        modifers.add(key.getKeyCode());
                                    }
                                    break;
                                default:
                                    events.add(new KeyEvent(new JPanel(),KeyEvent.KEY_PRESSED,System.currentTimeMillis(),getModifiers(modifers),key.getKeyCode(),key.getKeyChar()));
                                    break;
                            }
                            break;
                        case Release:
                            switch (key.getKeyCode()) {
                                case KeyEvent.VK_SHIFT:
                                case KeyEvent.VK_ALT:
                                case KeyEvent.VK_CONTROL:
                                case KeyEvent.VK_META:
                                    if (!modifers.contains(key.getKeyCode())) {
                                        modifers.remove(key.getKeyCode());
                                    }
                                    break;
                                default:
                                    events.add(new KeyEvent(new JPanel(),KeyEvent.KEY_RELEASED,key.getKeyChar()));
                                    break;
                            }
                            break;
                        case Type:
                            events.add(new KeyEvent(new JPanel(),key.getKeyChar()));
                            events.add(new KeyEvent(new JPanel(),KeyEvent.KEY_TYPED,KeyEvent.VK_UNDEFINED,key.getKeyChar()));
                            break;
                    }

                    for (KeyEvent evt : events) {
                        Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(evt);
                    }
                }
            } else {
                try {
                    SwingUtilities.invokeAndWait(new Runnable() {
                        @Override
                        public void run() {
                            dispatchKeyEventsViaEventQueue();
                        }
                    });
                } catch (Exception exp) {
                    exp.printStackTrace();
                }
            }
        }

        protected void dispatchKeyEventsViaRobot() {
            try {
                Robot robot = new Robot();
                String text = "This is a key sequence dispatched via java.awt.Robotn";
                KeySequence keySequence = getKeySequence(text);
                List<KeyEvent> events = new ArrayList<>();
                for (Key key : keySequence) {
                    events.clear();
                    System.out.println(key);
                    switch (key.getStrokeType()) {
                        case Press:
                            robot.keyPress(key.getKeyCode());
                            break;
                        case Release:
                            robot.keyRelease(key.getKeyCode());
                            break;
                        case Type:
                            robot.keyPress(key.getKeyCode());
                            robot.keyRelease(key.getKeyCode());
                            break;
                    }
                }
            } catch (AWTException exp) {
                exp.printStackTrace();
            }
        }
    }

    protected int getModifiers(List<Integer> mods) {
        int result = 0;
        for (int mod : mods) {
            result &= mod;
        }
        return result;
    }

    public static class Key {
        public enum StrokeType {
            Type,Press,Release
        }
        private StrokeType strokeType;
        private int keyCode;
        private char keyChar;
        public Key(StrokeType type,int keyCode,char keyChar) {
            this.strokeType = type;
            this.keyCode = keyCode;
            this.keyChar = keyChar;
        }

        public StrokeType getStrokeType() {
            return strokeType;
        }

        public int getKeyCode() {
            return keyCode;
        }

        public char getKeyChar() {
            return keyChar;
        }

        @Override
        public String toString() {
            return getStrokeType().name() + " " + getKeyChar() + " (" + getKeyCode() + ")";
        }
    }

    public static KeySequence getKeySequence(String text) {
        KeySequence ks = new KeySequence();
        for (char c : text.toCharArray()) {
            addKeySequence(ks,c);
        }
        return ks;
    }

    public static void addKeySequence(KeySequence ks,char character) {
        switch (character) {
            case 'a':
                ks.type(KeyEvent.VK_A,character);
                break;
            case 'b':
                ks.type(KeyEvent.VK_B,character);
                break;
            case 'c':
                ks.type(KeyEvent.VK_C,character);
                break;
            case 'd':
                ks.type(KeyEvent.VK_D,character);
                break;
            case 'e':
                ks.type(KeyEvent.VK_E,character);
                break;
            case 'f':
                ks.type(KeyEvent.VK_F,character);
                break;
            case 'g':
                ks.type(KeyEvent.VK_G,character);
                break;
            case 'h':
                ks.type(KeyEvent.VK_H,character);
                break;
            case 'i':
                ks.type(KeyEvent.VK_I,character);
                break;
            case 'j':
                ks.type(KeyEvent.VK_J,character);
                break;
            case 'k':
                ks.type(KeyEvent.VK_K,character);
                break;
            case 'l':
                ks.type(KeyEvent.VK_L,character);
                break;
            case 'm':
                ks.type(KeyEvent.VK_M,character);
                break;
            case 'n':
                ks.type(KeyEvent.VK_N,character);
                break;
            case 'o':
                ks.type(KeyEvent.VK_O,character);
                break;
            case 'p':
                ks.type(KeyEvent.VK_P,character);
                break;
            case 'q':
                ks.type(KeyEvent.VK_Q,character);
                break;
            case 'r':
                ks.type(KeyEvent.VK_R,character);
                break;
            case 's':
                ks.type(KeyEvent.VK_S,character);
                break;
            case 't':
                ks.type(KeyEvent.VK_T,character);
                break;
            case 'u':
                ks.type(KeyEvent.VK_U,character);
                break;
            case 'v':
                ks.type(KeyEvent.VK_V,character);
                break;
            case 'w':
                ks.type(KeyEvent.VK_W,character);
                break;
            case 'x':
                ks.type(KeyEvent.VK_X,character);
                break;
            case 'y':
                ks.type(KeyEvent.VK_Y,character);
                break;
            case 'z':
                ks.type(KeyEvent.VK_Z,character);
                break;
            case 'A':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_A,character);
                ks.release(KeyEvent.VK_SHIFT,'');
                break;
            case 'B':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_B,'');
                break;
            case 'C':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_C,'');
                break;
            case 'D':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_D,'');
                break;
            case 'E':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_E,'');
                break;
            case 'F':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_F,'');
                break;
            case 'G':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_G,'');
                break;
            case 'H':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_H,'');
                break;
            case 'I':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_I,'');
                break;
            case 'J':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_J,'');
                break;
            case 'K':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_K,'');
                break;
            case 'L':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_L,'');
                break;
            case 'M':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_M,'');
                break;
            case 'N':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_N,'');
                break;
            case 'O':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_O,'');
                break;
            case 'P':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_P,'');
                break;
            case 'Q':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_Q,'');
                break;
            case 'R':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_R,'');
                break;
            case 'S':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_S,'');
                break;
            case 'T':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_T,'');
                break;
            case 'U':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_U,'');
                break;
            case 'V':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_V,'');
                break;
            case 'W':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_W,'');
                break;
            case 'X':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_X,'');
                break;
            case 'Y':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_Y,'');
                break;
            case 'Z':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_Z,'');
                break;
            case '`':
                ks.type(KeyEvent.VK_BACK_QUOTE,character);
                break;
            case '0':
                ks.type(KeyEvent.VK_0,character);
                break;
            case '1':
                ks.type(KeyEvent.VK_1,character);
                break;
            case '2':
                ks.type(KeyEvent.VK_2,character);
                break;
            case '3':
                ks.type(KeyEvent.VK_3,character);
                break;
            case '4':
                ks.type(KeyEvent.VK_4,character);
                break;
            case '5':
                ks.type(KeyEvent.VK_5,character);
                break;
            case '6':
                ks.type(KeyEvent.VK_6,character);
                break;
            case '7':
                ks.type(KeyEvent.VK_7,character);
                break;
            case '8':
                ks.type(KeyEvent.VK_8,character);
                break;
            case '9':
                ks.type(KeyEvent.VK_9,character);
                break;
            case '-':
                ks.type(KeyEvent.VK_MINUS,character);
                break;
            case '=':
                ks.type(KeyEvent.VK_EQUALS,character);
                break;
            case '~':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_BACK_QUOTE,'');
                break;
            case '!':
                ks.type(KeyEvent.VK_EXCLAMATION_MARK,character);
                break;
            case '@':
                ks.type(KeyEvent.VK_AT,character);
                break;
            case '#':
                ks.type(KeyEvent.VK_NUMBER_SIGN,character);
                break;
            case '$':
                ks.type(KeyEvent.VK_DOLLAR,character);
                break;
            case '%':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_5,'');
                break;
            case '^':
                ks.type(KeyEvent.VK_CIRCUMFLEX,character);
                break;
            case '&':
                ks.type(KeyEvent.VK_AMPERSAND,character);
                break;
            case '*':
                ks.type(KeyEvent.VK_ASTERISK,character);
                break;
            case '(':
                ks.type(KeyEvent.VK_LEFT_PARENTHESIS,character);
                break;
            case ')':
                ks.type(KeyEvent.VK_RIGHT_PARENTHESIS,character);
                break;
            case '_':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_MINUS,'');
                break;
            case '+':
                ks.type(KeyEvent.VK_PLUS,character);
                break;
            case 't':
                ks.type(KeyEvent.VK_TAB,character);
                break;
            case 'n':
                ks.type(KeyEvent.VK_ENTER,character);
                break;
            case '[':
                ks.type(KeyEvent.VK_OPEN_BRACKET,character);
                break;
            case ']':
                ks.type(KeyEvent.VK_CLOSE_BRACKET,character);
                break;
            case '':
                ks.type(KeyEvent.VK_BACK_SLASH,character);
                break;
            case '{':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_OPEN_BRACKET,'');
                break;
            case '}':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_CLOSE_BRACKET,'');
                break;
            case '|':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_BACK_SLASH,'');
                break;
            case ';':
                ks.type(KeyEvent.VK_SEMICOLON,character);
                break;
            case ':':
                ks.type(KeyEvent.VK_COLON,character);
                break;
            case ''':
                ks.type(KeyEvent.VK_QUOTE,character);
                break;
            case '"':
                ks.type(KeyEvent.VK_QUOTEDBL,character);
                break;
            case ',':
                ks.type(KeyEvent.VK_COMMA,character);
                break;
            case '<':
                ks.type(KeyEvent.VK_LESS,character);
                break;
            case '.':
                ks.type(KeyEvent.VK_PERIOD,character);
                break;
            case '>':
                ks.type(KeyEvent.VK_GREATER,character);
                break;
            case '/':
                ks.type(KeyEvent.VK_SLASH,character);
                break;
            case '?':
                ks.press(KeyEvent.VK_SHIFT,'');
                ks.type(KeyEvent.VK_SLASH,'');
                break;
            case ' ':
                ks.type(KeyEvent.VK_SPACE,character);
                break;
            default:
                throw new IllegalArgumentException("Cannot type character " + character);
        }
    }

    public static class KeySequence implements Iterable<Key> {
        private List<Key> keys;
        public KeySequence() {
            keys = new ArrayList<>(25);
        }

        public void type(int keyCode,char keyChar) {
            keys.add(new Key(Key.StrokeType.Type,keyCode,keyChar));
        }

        public void press(int keyCode,char keyChar) {
            keys.add(new Key(Key.StrokeType.Press,keyChar));
        }

        public void release(int keyCode,char keyChar) {
            keys.add(new Key(Key.StrokeType.Release,keyChar));
        }

        public Iterator<Key> iterator() {
            return keys.iterator();
        }
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读