Awt机器人按键延迟

Awt Robot key press delay

我正在为游戏开发一个小工具,比如热键,它处理用户按键事件的组合,并用 Awt Robot 模拟几次按键。问题是被调用的方法 ghostWalk() 仅在第一次按下注册组合时按预期工作,第二次当我按下相同的组合并调用相同的方法时,仅模拟了 "robot.delay" 之后的最后一个键。请从代码注释中阅读更多内容。

import com.melloware.jintellitype.HotkeyListener;
import com.melloware.jintellitype.JIntellitype;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;

public class L {
int i = 160;

public static void main(String args[]){
    L l = new L();
    l.k();
}
public void k(){
    // Register keys combination
    JIntellitype.getInstance();
    JIntellitype.getInstance().registerHotKey(1, JIntellitype.MOD_ALT, (int)'D');
    JIntellitype.getInstance().registerHotKey(2, JIntellitype.MOD_ALT, (int)'J');
    JIntellitype.getInstance().registerHotKey(3, JIntellitype.MOD_ALT, (int)'K');
    JIntellitype.getInstance().addHotKeyListener(new HotkeyListener() {
        public void onHotKey(int aIdentifier) {
            // First indentifier Alt + D
            if (aIdentifier == 1) {
                System.out.println("Alt+D hotkey pressed");
                // Start new thread
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        L gh = new L();
                        gh.ghostWalk();
                    }
                }).start();
            }
            // Second indetifier
            else if(aIdentifier == 2){
                i += 10;
                System.out.println(i);
            }
            // Third
            else if(aIdentifier == 3){
                i -= 10;
                System.out.println(i);
            }
        }
    });
}
// Method called to simulate key press
/* So, first time when i press Alt + D in game after program runs
all work good, the keys are simulated  as expected but if I press again and again
the combination only key "d" are simulated which is after "delay(i), i = 160"
If program is restarted all again is the same, only first time when i press registered
combinations the program work as expected.
Second and others times program work only if there is delay "robot = new Robot();
                                                             robot.delay(100);"
 on 100 delay program work well on 40ms need to press very fast the combination
 so the program work as expected. How to fix it ? to simulate key press without
 delay like first time when program is run.
 P.s no matter in which window(game, notepad) you press combination to simulate key press
 still work good only first time.
Example of output when i press two times combinations in game
first time: qqwewwd
second time: d
 */
public void ghostWalk(){
    Robot robot = null;
    try {
        robot = new Robot();
        //robot.delay(100);
        robot.keyPress(KeyEvent.VK_Q);
        robot.keyRelease(KeyEvent.VK_Q);
        robot.keyPress(KeyEvent.VK_Q);
        robot.keyRelease(KeyEvent.VK_Q);
        robot.keyPress(KeyEvent.VK_W);
        robot.keyRelease(KeyEvent.VK_W);
        robot.keyPress(KeyEvent.VK_R);
        robot.keyRelease(KeyEvent.VK_R);
        robot.keyPress(KeyEvent.VK_W);
        robot.keyRelease(KeyEvent.VK_W);
        robot.keyPress(KeyEvent.VK_W);
        robot.keyRelease(KeyEvent.VK_W);
        robot.delay(i);
        robot.keyPress(KeyEvent.VK_D);
        robot.keyRelease(KeyEvent.VK_D);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

编辑:我不明白在第一次调用 ghostWalk 方法后做了哪些更改,我应该使用延迟,以便我的程序按预期工作。

Edit2: 在我的例子中,代码在 setAutoWaitForIdle 设置为 true 且 delay = 5 时开始工作(在开始模拟按键之前延迟)也如果介于 按键是一个延迟,就像我的例子 delay(i), i = 160 那么开始延迟应该是 60~。 (如果启动延迟是 40~ 那么并不总是很好,需要非常快地按下注册键组合 idk 为什么,如果启动延迟小于 40-60 在我的情况下只模拟最后一次按键 "D" 之后延迟(i).)

如果在第一次注册的热键事件中删除 robot.setAutoWaitForIdle(true)robot.delay(60),该工具将按预期工作,但在第二次、第三次等时不会。在第一个 JIntellitype 事件之后仅此代码起作用。

public void ghostWalk(){
    Robot robot = null;
    try {
        robot = new Robot();
        robot.setAutoWaitForIdle(true);
        robot.delay(60);
        robot.keyPress(KeyEvent.VK_Q);
        robot.keyRelease(KeyEvent.VK_Q);
        robot.keyPress(KeyEvent.VK_Q);
        robot.keyRelease(KeyEvent.VK_Q);
        robot.keyPress(KeyEvent.VK_W);
        robot.keyRelease(KeyEvent.VK_W);
        robot.keyPress(KeyEvent.VK_R);
        robot.keyRelease(KeyEvent.VK_R);;
        robot.delay(i);
        robot.keyPress(KeyEvent.VK_D);
        robot.keyRelease(KeyEvent.VK_D);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

您应该考虑使用 setAutoDelay 设置自动延迟。

很可能您的 OS 在处理输入事件时遇到问题,如果它们被立即发布的话。尝试延迟 50 毫秒或 25 毫秒,看看会发生什么。

您可以尝试的另一件事是在每次按键前添加 waitForIdle()


编辑: 对于运动,我尝试了 JIntelliType library out, and the following snippet works relatively well. I tested pressing the hotkey out in Notepad++ (ctrl-Q),它始终打印出 tt rocks。但是我必须快速释放热键,否则 Notepad++ 开始将热键解释为其他东西(ctrl-Q 已经是 Notepad++ 中其他东西的快捷方式)。

使用机器人并不是一门精确的科学。在让机器人按键之前,我不得不延迟机器人 150 毫秒然后 waitForIdle。否则事情就搞砸了。无需设置自动延迟。

import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import com.melloware.jintellitype.HotkeyListener;
import com.melloware.jintellitype.JIntellitype;

public class TestKeys {
    private HotkeyListener listener = new HotkeyListener() {
        @Override
        public void onHotKey(final int hotKeyId) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    JIntellitype.getInstance().removeHotKeyListener(listener);
                    handleHotKey(hotKeyId);
                    JIntellitype.getInstance().addHotKeyListener(listener);
                }
            }).start();
        }
    };

    public void registerHotKeys() {
        JIntellitype instance = JIntellitype.getInstance();
        instance.registerHotKey(1, JIntellitype.MOD_CONTROL, 'Q');
        instance.registerHotKey(2, JIntellitype.MOD_CONTROL, 'J');
        instance.addHotKeyListener(listener);
        System.out.println("Hotkeys registered");
    }

    private static void handleHotKey(int hotKeyId) {
        switch(hotKeyId) {
            case 1:
                System.out.println("Pressing some keys now!");
                pressSomeKeys();
                break;
            case 2:
                System.out.println("Bailing out, cya!");
                System.exit(0);
                break;
        }
    }

    private static void pressSomeKeys() {
        Robot r;
        try {
            r = new Robot();
        } 
        catch (AWTException e) {
            System.out.println("Creating robot failed");
            System.exit(2);
            return;
        }
        r.setAutoWaitForIdle(true);
        r.delay(150);
        r.waitForIdle();
        r.keyPress(KeyEvent.VK_T); r.keyRelease(KeyEvent.VK_T);
        r.keyPress(KeyEvent.VK_T); r.keyRelease(KeyEvent.VK_T);
        r.keyPress(KeyEvent.VK_SPACE); r.keyRelease(KeyEvent.VK_SPACE);
        r.keyPress(KeyEvent.VK_R); r.keyRelease(KeyEvent.VK_R);
        r.keyPress(KeyEvent.VK_O); r.keyRelease(KeyEvent.VK_O);
        r.keyPress(KeyEvent.VK_C); r.keyRelease(KeyEvent.VK_C);
        r.keyPress(KeyEvent.VK_K); r.keyRelease(KeyEvent.VK_K);
        r.keyPress(KeyEvent.VK_S); r.keyRelease(KeyEvent.VK_S);
    }

    public static synchronized void main(String[] args) {
        System.out.println("TestKeys started");
        TestKeys k = new TestKeys();
        k.registerHotKeys();
        try { 
            TestKeys.class.wait();
        } 
        catch (InterruptedException e) {
        }
    }
}