如何在最终用户键入某些东西时,构建自己的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 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();
- }
- }
- }