【问题标题】:Awt Robot key press delayAwt 机器人按键延迟
【发布时间】:2016-02-13 20:09:36
【问题描述】:

我正在开发一个用于游戏的小工具,比如热键,它处理用户按键事件的组合并使用 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(开始模拟按键之前的延迟)时,代码开始工作,如果介于两者之间 keypress 是一个延迟,就像在我的情况下 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();
    }
}

【问题讨论】:

  • 你是说如果你增加延迟,你的程序按预期工作,但你不想延迟?
  • 是的..例如在蒸汽中或在其他软件中,当您按 alt 时按预期工作不会改变焦点,然后我按 Alt D 没有延迟,没有错,一切都很好。首先,我认为这可能是一些游戏限制,但第一次完美运行 + 我有一个不是我编写的工具,它可以像我想在我的工具中做的那样与游戏一起工作。

标签: java awtrobot jintellitype


【解决方案1】:

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

如果没有延迟地发布输入事件,您的操作系统很可能在处理输入事件时遇到问题。尝试延迟 50 毫秒或 25 毫秒,看看会发生什么。

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


编辑: 对于运动,我尝试了JIntelliType library,以下 sn-p 效果相对较好。我测试了在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) {
        }
    }
}

【讨论】:

  • 好吧,我知道为什么当 robot.setAutoDelay(50);第一个 q 不是写,所有其他的工作,但很慢。
  • @N.A Well 50ms 只是一个例子; 25ms 也可以。我用另一个建议 (waitForIdle) 更新了我的答案。如果这不起作用,也许你可以添加一个 fake 按键,如果它总是被忽略的第一个按键。
  • TT。感谢帮助。请在我编辑他的时候再阅读一次主帖,如果您对此有一些想法,请告诉我,如果不只是告诉我类似“不,谢谢”之类的话,这样我就可以接受您的回答,我只是不知道您是我还是我如果我现在接受你的回答,我仍然可以在这个帖子中发表评论。
  • @N.A 我已经用一个在我的系统上运行良好的 sn-p 更新了我的答案。
  • 您的代码在启动延迟 150 或 100 甚至 60 时运行良好,如果您按下非常快,但您和我的代码之间没有区别,两者的启动延迟都超过 60。您可以重现我的如果您在代码中将延迟减少到 5 或 10 并在 Steam 商店搜索文本框中尝试它,则在 Steam 中,当您按下 Alt 或 Ctrl 时,文本框的焦点不会移出。您可能会在第一次注册的热键事件中看到代码运行良好,并且“tt Rocks”正在按预期写入,但在第二次事件中,无论您尝试多少次,都只会写入空间。
猜你喜欢
  • 2012-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-03
  • 1970-01-01
  • 2019-08-05
相关资源
最近更新 更多