You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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]);
    }
}

关键说明

  1. 西班牙语键盘大量使用Alt Gr(对应KeyEvent.VK_ALT_GRAPH)组合键输入特殊符号,需严格遵循「先按修饰键、再按目标键、最后依次释放」的顺序。
  2. 原代码遗漏字母按键的释放操作,会导致按键被持续按住,补充后可避免输入异常。
  3. 重复创建Robot实例会影响性能,改为复用实例更高效。

内容的提问来源于stack exchange,提问作者JLLMNCHR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 16:36:10