【问题标题】:getKeyStroke(char) vs. getKeyStroke(char, int) - I don't understand the differencegetKeyStroke(char) 与 getKeyStroke(char, int) - 我不明白区别
【发布时间】:2015-10-25 18:26:54
【问题描述】:

此代码始终返回 0:

KeyStroke.getKeyStroke(someString.charAt(0)).getKeyCode();

虽然这个返回的是实际的键码:

KeyStroke.getKeyStroke(someString.charAt(0), 0).getKeyCode();

但是,我不明白 getKeyStroke() 中的第二个参数有什么用。 documentation 没有解释任何东西,除了这个参数被称为“修饰符”,它似乎不会以任何方式影响键码,与我放在那里的数字无关。

我很高兴得到解释。

【问题讨论】:

标签: java parameters keystroke


【解决方案1】:

您需要了解 keyPressed、keyTyped 和 keyReleased 事件之间的区别。

在第一种情况下,会生成 keyTyped 事件。在第二种情况下,会生成一个keyPressed 事件。

然后您需要查看KeyEvent API,您可以在其中找到:

对于按键按下和按键释放事件,getKeyCode 方法返回事件的 keyCode。对于键类型事件,getKeyCode 方法总是返回 VK_UNDEFINED。

编辑:

其实上面的回答还不够完整。查看以下演示代码:

public class Main
{
    public static void main(String[] args) throws Exception
    {
        KeyStroke ks1 = KeyStroke.getKeyStroke( 'a' );
        System.out.println( ks1 );
        KeyStroke ks2 = KeyStroke.getKeyStroke('a', 0);
        System.out.println( ks2 );
    }
}

我得到以下输出:

typed a
pressed NUMPAD1

来自getKeyStroke(Character keyChar, int modifiers) API:

请注意,第一个参数的类型是 Character 而不是 char。这是为了避免与调用 getKeyStroke(int keyCode, int modifiers) 发生意外冲突。

所以,我想说修饰符与问题无关。问题是 'a' 被视为 int 并映射到与您预期不同的 KeyStroke。

尝试使用机器人生成角色总是有风险的。下面是一个您可以使用的简单示例:

import java.awt.*;
import java.util.*;
import java.lang.reflect.Field;
import java.awt.event.*;
import javax.swing.*;

public class RobotCharacter
{
    public static void main(String[] args)
        throws Exception
    {
        JTextField textField = new JTextField(10);

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add( textField );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );

        Robot robot = new Robot();
        typeCharacter(robot, "a");
        typeCharacter(robot, "b");
        typeCharacter(robot, "C");
        typeCharacter(robot, "D");
     }

    public static void typeCharacter(Robot robot, String letter)
    {
        try
        {
            boolean upperCase =  
                    Character.isUpperCase(letter.charAt(0) );
            String variableName = "VK_" + letter.toUpperCase();

            Class clazz = KeyEvent.class;
            Field field = clazz.getField( variableName );
            int keyCode = field.getInt(null);

            robot.delay(1000);

            if (upperCase)
            {
                robot.keyPress( KeyEvent.VK_SHIFT );
            }
            robot.keyPress( keyCode );
            robot.keyRelease( keyCode );

            if (upperCase)
            {
                robot.keyRelease( KeyEvent.VK_SHIFT );
            }
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}

适用于字母/数字,但您总是会遇到特殊字符($、%、&...)的问题。我建议您寻找一种不同的方法,而不是使用机器人。

您可以尝试创建一个字符的 Hashmap 及其对应的 KeyEvent.VK_???。即使这种方法也有问题,因为有些字符需要 shift 键,而有些键盘不同,所以有些可能需要 shift 键,有些可能不需要。

【讨论】:

  • 谢谢,这对我来说有点道理。但这带来了一个后续问题:“一组修饰符,指定按下或释放键时是否激活” - 这对我来说没有意义,因为我只将它与java.awt.Robot 类到目前为止。所以我不明白“密钥是否被激活”是什么意思。我的理解是,如果我调用 Robot.keyPress(keyCode),则会模拟击键。
  • 哦,我从来没有用移位的特殊字符测试过它......但我做的事情和你用“大写”检查做的一样,这就是为什么我仍然没有得到在这种情况下使用修饰符。但是我从今天的答案中学到了一些东西。感谢您花时间制作这个“独立”示例并解释了这么多!
  • I still don't get the use of the modifiers for this scenario. - 值为 0,因此您没有使用修饰符。修饰符对键码没有意义。
【解决方案2】:

修饰符是按位掩码,用于同时按下例如ctrl 按钮或 shift 按钮。不要只是在其中输入任何数字。

KeyStroke.getKeyStroke('a', java.awt.event.InputEvent.SHIFT_DOWN_MASK | java.awt.event.InputEvent.CTRL_DOWN_MASK);

如果 ctrl 或 shift 按钮应该用 'a' 按下,这将是修饰符的正确用法

【讨论】:

  • 好的,我在控制台中看到了不同之处。但是在模拟击键时,修饰符并不重要,不是吗?因为 java.awt.Robot.keyPress() 只需要 keyCodes (int) 并且如 OP 中所述,修饰符不会(似乎)影响键码。
猜你喜欢
  • 1970-01-01
  • 2014-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
  • 2020-10-08
相关资源
最近更新 更多