使用java.awt.Robot在西班牙语键盘无法输入部分符号的问题
Java AWT Robot 适配西班牙语键盘输入特殊符号方案
问题描述
使用java.awt.Robot类配合下图的西班牙语键盘时,无法模拟输入以下符号:
{ } [ ] ~ @ # ^ \ |

原测试代码如下:
package test; import java.awt.Robot; import java.awt.event.KeyEvent; public class Principal5 { public static void main(String[] args) throws Exception { Runtime.getRuntime().exec("notepad.exe"); sleep(2000); writeString("aAbBcC012345();{} -=_+\t\n[]:\" ,<.>~!@#$%^&*\\|'/¿?ñ¡"); } private static void writeString(String str) throws Exception { Robot robot = new Robot(); // Press keys using robot char car; for (int i = 0; i < str.length(); i++) { car = str.charAt(i); try { // Check if the current character is a capital letter if (Character.isUpperCase(car)) { // Press shift key robot.keyPress(KeyEvent.VK_SHIFT); // Press the current character robot.keyPress(Character.toUpperCase(car)); // Release shift key robot.keyRelease(KeyEvent.VK_SHIFT); } else if (Character.isLetter(car)) { // else display the character as it is robot.keyPress(Character.toUpperCase(car)); } else { symbolPress(car); } } catch (Exception e1) { System.out.println("Exception for character " + car + " " + e1.getMessage()); } // wait for 200ms sleep(200); } robot.keyPress(KeyEvent.VK_ENTER); robot.keyRelease(KeyEvent.VK_ENTER); } private static void symbolPress(char car) throws Exception { switch (car) { case ';': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_COMMA); break; case '(': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_8); break; case ')': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_9); break; /* case '{': doType(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_BACK_QUOTE); break; case '}': doType(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_DEAD_CEDILLA); break; */ case ' ': doType(KeyEvent.VK_SPACE); break; case '-': doType(KeyEvent.VK_MINUS); break; case '=': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_0); break; case '_': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_MINUS); break; case '+': doType(KeyEvent.VK_PLUS); break; case '\t': doType(KeyEvent.VK_TAB); break; case '\n': doType(KeyEvent.VK_ENTER); break; /* case '[': doType(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_OPEN_BRACKET); break; case ']': doType(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_PLUS); break; */ case ':': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_PERIOD); break; case '"': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_2); break; case ',': doType(KeyEvent.VK_COMMA); break; case '<': doType(KeyEvent.VK_LESS); break; case '.': doType(KeyEvent.VK_PERIOD); break; case '>': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_LESS); break; case '0': doType(KeyEvent.VK_0); break; case '1': doType(KeyEvent.VK_1); break; case '2': doType(KeyEvent.VK_2); break; case '3': doType(KeyEvent.VK_3); break; case '4': doType(KeyEvent.VK_4); break; case '5': doType(KeyEvent.VK_5); break; case '6': doType(KeyEvent.VK_6); break; case '7': doType(KeyEvent.VK_7); break; case '8': doType(KeyEvent.VK_8); break; case '9': doType(KeyEvent.VK_9); break; /* case '~': doType(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_4, KeyEvent.VK_ENTER); break; case '@': doType(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_2); break; case '#': doType(KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_3); break; case '^': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_OPEN_BRACKET); break; case '\\': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_SLASH); break; case '|': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_BACK_SLASH); break; */ case '!': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_1); break; case '¡': doType(KeyEvent.VK_INVERTED_EXCLAMATION_MARK); break; case '$': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_4); break; case '%': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_5); break; case '&': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_6); break; case '*': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_PLUS); break; case '\'': doType(KeyEvent.VK_QUOTE); break; case '/': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_7); break; case '?': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_QUOTE); break; case '¿': doType(KeyEvent.VK_SHIFT, KeyEvent.VK_INVERTED_EXCLAMATION_MARK); break; /* case '`': doType(KeyEvent.VK_BACK_QUOTE); break; */ default: System.out.println("Not cathegorized character " + car); } } private static void doType(int... keyCodes) throws Exception { doType(keyCodes, 0, keyCodes.length); } private static void doType(int[] keyCodes, int offset, int length) throws Exception { if (length > 0) { Robot robot = new Robot(); robot.keyPress(keyCodes[offset]); doType(keyCodes, offset + 1, length - 1); robot.keyRelease(keyCodes[offset]); } } // Our custom sleep method public static void sleep(long ms) { try { Thread.sleep(ms); } catch (Exception ignored) { // Se ignora } } }
问题原因
原代码中针对特殊符号的按键映射不符合西班牙语键盘的实际布局,且部分符号的KeyEvent常量使用错误,同时遗漏了字母按键的释放逻辑,导致无法正确触发对应输入组合。
修正方案
1. 修正特殊符号的按键映射
修改symbolPress方法中注释的符号逻辑,替换为符合西班牙语键盘的组合键:
private static void symbolPress(char car, Robot robot) throws Exception { switch (car) { case ';': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_COMMA); break; case '(': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_8); break; case ')': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_9); break; // 修正特殊符号映射 case '{': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_BACK_QUOTE); break; case '}': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_DEAD_ACUTE); break; case ' ': doType(robot, KeyEvent.VK_SPACE); break; case '-': doType(robot, KeyEvent.VK_MINUS); break; case '=': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_0); break; case '_': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_MINUS); break; case '+': doType(robot, KeyEvent.VK_PLUS); break; case '\t': doType(robot, KeyEvent.VK_TAB); break; case '\n': doType(robot, KeyEvent.VK_ENTER); break; // 修正特殊符号映射 case '[': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_8); break; case ']': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_9); break; case ':': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_PERIOD); break; case '"': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_2); break; case ',': doType(robot, KeyEvent.VK_COMMA); break; case '<': doType(robot, KeyEvent.VK_LESS); break; case '.': doType(robot, KeyEvent.VK_PERIOD); break; case '>': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_LESS); break; case '0': doType(robot, KeyEvent.VK_0); break; case '1': doType(robot, KeyEvent.VK_1); break; case '2': doType(robot, KeyEvent.VK_2); break; case '3': doType(robot, KeyEvent.VK_3); break; case '4': doType(robot, KeyEvent.VK_4); break; case '5': doType(robot, KeyEvent.VK_5); break; case '6': doType(robot, KeyEvent.VK_6); break; case '7': doType(robot, KeyEvent.VK_7); break; case '8': doType(robot, KeyEvent.VK_8); break; case '9': doType(robot, KeyEvent.VK_9); break; // 修正特殊符号映射 case '~': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_4); break; case '@': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_2); break; case '#': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_3); break; case '^': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_6); break; case '\\': doType(robot, KeyEvent.VK_ALT_GRAPH, KeyEvent.VK_LESS); break; case '|': doType(robot, KeyEvent.VK_BACK_QUOTE); break; case '!': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_1); break; case '¡': doType(robot, KeyEvent.VK_INVERTED_EXCLAMATION_MARK); break; case '$': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_4); break; case '%': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_5); break; case '&': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_6); break; case '*': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_PLUS); break; case '\'': doType(robot, KeyEvent.VK_QUOTE); break; case '/': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_7); break; case '?': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_QUOTE); break; case '¿': doType(robot, KeyEvent.VK_SHIFT, KeyEvent.VK_INVERTED_EXCLAMATION_MARK); break; case '`': doType(robot, KeyEvent.VK_BACK_QUOTE); break; default: System.out.println("Not cathegorized character " + car); } }
2. 补充按键释放逻辑并复用Robot实例
修改writeString和doType方法,避免重复创建Robot实例,同时补充遗漏的按键释放操作:
private static void writeString(String str) throws Exception { Robot robot = new Robot(); char car; for (int i = 0; i < str.length(); i++) { car = str.charAt(i); try { if (Character.isUpperCase(car)) { robot.keyPress(KeyEvent.VK_SHIFT); robot.keyPress(Character.toUpperCase(car)); robot.keyRelease(Character.toUpperCase(car)); robot.keyRelease(KeyEvent.VK_SHIFT); } else if (Character.isLetter(car)) { robot.keyPress(Character.toUpperCase(car)); robot.keyRelease(Character.toUpperCase(car)); } else { symbolPress(car, robot); } } catch (Exception e1) { System.out.println("Exception for character " + car + " " + e1.getMessage()); } sleep(200); } robot.keyPress(KeyEvent.VK_ENTER); robot.keyRelease(KeyEvent.VK_ENTER); } private static void doType(Robot robot, int... keyCodes) throws Exception { doType(robot, keyCodes, 0, keyCodes.length); } private static void doType(Robot robot, int[] keyCodes, int offset, int length) throws Exception { if (length > 0) { robot.keyPress(keyCodes[offset]); doType(robot, keyCodes, offset + 1, length - 1); robot.keyRelease(keyCodes[offset]); } }
关键说明
- 西班牙语键盘大量使用
Alt Gr(对应KeyEvent.VK_ALT_GRAPH)组合键输入特殊符号,需严格遵循「先按修饰键、再按目标键、最后依次释放」的顺序。 - 原代码遗漏字母按键的释放操作,会导致按键被持续按住,补充后可避免输入异常。
- 重复创建
Robot实例会影响性能,改为复用实例更高效。
内容的提问来源于stack exchange,提问作者JLLMNCHR
相关产品推荐
相关产品推荐

