Java – how to perfectly simulate keyevents?

How do you build your own keyevent object when the end user types something, which perfectly (or very closely) matches the object received from the keylistener?

For example, I have a British ISO keyboard layout and type the character "I press shift 2". If I record it on JFrame with a keylistener, I receive the following event:

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

I want to create a method. I will give "as a char parameter, it will return an array of keyevents listed above

My question is:

>In key_ Pressed and key_ In the released event, keychar = '"' indicates the pressed character ("), but keycode = 50 indicates the "non shifted" ASCII value (also known as 2) I need to know how to get this non shifted value from "character". > This non shift value will be different for different keyboard layouts For example, American ANSI layout requires shift 'to type "key, which means that the keycode will be 39 instead of 50. > on some keyboard layouts, you need to use shift key to type keys, but you don't need keys. For example, # characters need to use shift 3 on American ANSI keyboard, but you don't need to press the move key on British ISO keyboard. I need to know whether to simulate shift button / release event and provide shift modifier

Any ideas on how to solve these problems will be appreciated I should also note that the robot class cannot be used in my case

Solution

There is no "easy" way to convert a virtual key to an actual key sequence or return again, at least I didn't find it

The two main ways to schedule key events are through Java awt. Robot or directly through the system event queue What you want to use will depend on what you want to achieve

Components usually can't distinguish the key strokes that you generate your self from the keyboard

The following example is very complex. Sorry, I find there is no better way to meet my requirements

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 queue\n";
                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.Robot\n";
                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,'\0');
                ks.type(KeyEvent.VK_A,character);
                ks.release(KeyEvent.VK_SHIFT,'\0');
                break;
            case 'B':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_B,'\0');
                break;
            case 'C':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_C,'\0');
                break;
            case 'D':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_D,'\0');
                break;
            case 'E':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_E,'\0');
                break;
            case 'F':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_F,'\0');
                break;
            case 'G':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_G,'\0');
                break;
            case 'H':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_H,'\0');
                break;
            case 'I':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_I,'\0');
                break;
            case 'J':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_J,'\0');
                break;
            case 'K':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_K,'\0');
                break;
            case 'L':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_L,'\0');
                break;
            case 'M':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_M,'\0');
                break;
            case 'N':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_N,'\0');
                break;
            case 'O':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_O,'\0');
                break;
            case 'P':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_P,'\0');
                break;
            case 'Q':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_Q,'\0');
                break;
            case 'R':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_R,'\0');
                break;
            case 'S':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_S,'\0');
                break;
            case 'T':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_T,'\0');
                break;
            case 'U':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_U,'\0');
                break;
            case 'V':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_V,'\0');
                break;
            case 'W':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_W,'\0');
                break;
            case 'X':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_X,'\0');
                break;
            case 'Y':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_Y,'\0');
                break;
            case 'Z':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_Z,'\0');
                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,'\0');
                ks.type(KeyEvent.VK_BACK_QUOTE,'\0');
                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,'\0');
                ks.type(KeyEvent.VK_5,'\0');
                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,'\0');
                ks.type(KeyEvent.VK_MINUS,'\0');
                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,'\0');
                ks.type(KeyEvent.VK_OPEN_BRACKET,'\0');
                break;
            case '}':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_CLOSE_BRACKET,'\0');
                break;
            case '|':
                ks.press(KeyEvent.VK_SHIFT,'\0');
                ks.type(KeyEvent.VK_BACK_SLASH,'\0');
                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,'\0');
                ks.type(KeyEvent.VK_SLASH,'\0');
                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();
        }
    }
}
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>