Прослушивание ввода без фокуса в Java - PullRequest
20 голосов
/ 23 мая 2009

Я делаю небольшую программу на Java, используя класс Robot. Программа берет на себя мышь. в то время как в процессе отладки, если он начинает работать так, как я не хочу, трудно выйти из программы, так как я не могу переместить мышь к кнопке завершения в затмении, и я не могу использовать горячие клавиши для ударил его, потому что мышь постоянно щелкает в другом окне, вместо этого давая этому окну фокус.

Что я хотел бы сделать, так это просто подключить список ключей, чтобы, когда я нажимаю q, я мог выйти из программы, но единственный способ, которым я знаю, как это сделать, заключается в создании окна, и это окно должно быть сфокусировано для захвата вход. Есть ли способ прослушивания ввода с клавиатуры или мыши откуда угодно, независимо от того, на чем фокус?

Ответы [ 6 ]

21 голосов
/ 20 октября 2013

Есть библиотека, которая делает тяжелую работу за вас: https://github.com/kwhat/jnativehook

13 голосов
/ 24 мая 2009

Это не тривиальная проблема, и Java не дает вам способа сделать это элегантно. Вы можете использовать решение, подобное предложенному banjollity, но даже оно не будет работать постоянно, если ваши ошибочные щелчки мыши откроют другое полноразмерное окно, открытое в настоящее время на панели задач, например.

Дело в том, что Java по умолчанию дает разработчикам очень мало контроля над ОС. Это связано с двумя основными причинами: безопасность (как указано в документации java) и тот факт, что разные операционные системы обрабатывают события совершенно по-разному, и создание единой модели для представления всех из них, вероятно, не имеет большого смысла.

Итак, чтобы ответить на ваш вопрос, я представляю, что вам нужно какое-то поведение для вашей программы, когда она прослушивает нажатия клавиш глобально, а не только в вашем приложении. Что-то вроде этого потребует от вас доступа к функциональности, предлагаемой выбранной вами ОС, и для доступа к ней в Java вам потребуется сделать это через уровень Java Native Interface (JNI).

Итак, что вы хотите сделать, это:

  1. Реализуйте программу на C, которая будет прослушивать глобальные нажатия клавиш в вашей ОС, если эта ОС является Windows, чем искать документацию по хукам Windows, которая хорошо документирована Microsoft и MSDN в Интернете и других местах. Если ваша операционная система Linux или Mac OS X, вам нужно будет прослушивать глобальные нажатия клавиш, используя библиотеки разработки X11. Это можно сделать на дистрибутиве Ubuunutu Linux в соответствии с инструкциями, которые я написал на http://ubuntuforums.org/showthread.php?t=864566

  2. Подключите ваш код C к вашему Java-коду через JNI. Этот шаг на самом деле является более легким шагом. Следуйте процедуре, которую я использую в моем руководстве по адресу http://ubuntuforums.org/showthread.php?t=864566 для обоих окон и Linux, поскольку процедура подключения вашего кода C к вашему Java-коду будет идентична в обеих ОС.

Важно помнить, что намного легче заставить работать ваш код JNI, если вы сначала запрограммируете и отладите свой код C / C ++ и убедитесь, что он работает. Тогда его легко интегрировать с Java.

2 голосов
/ 06 октября 2010

Была такая же проблема. В моем случае робот просто контролировал одно приложение Windows, которое было максимизировано. Я разместил эти строки в верхней части основного цикла, управляющего роботом:

Цвет iconCenterColor = новый цвет (255,0,0); // если значок программы красный

if (iconCenterColor.equals (robot.getPixelColor (10,15))) выдать новое IllegalStateException («робот не взаимодействует с нужным приложением.»);

Чтобы отменить робота, просто нажмите alt-tab для другого приложения. Прекрасно работает для простого робота, управляющего одним приложением.

1 голос
/ 24 мая 2009

Запустите программу из командной строки в терминале и используйте Ctrl-C, чтобы завершить ее.

0 голосов
/ 05 августа 2014

Вот простой Java-способ сделать это для решения описанной вами проблемы (не проблема KeyListener ... завершить тестирование при использовании робота):

На протяжении всего теста сравнивайте положение мыши с тем, которое недавно было задано в вашем тесте. Если это не соответствует, выйдите из теста. Примечание: важная часть этого кода - это метод testPosition. Вот код, который я недавно использовал:

public void testSomething() throws Exception {
    try {
        // snip

        // you can even extract this into a method "clickAndTest" or something
        robot.mouseMove(x2, y2);
        click();
        testPosition(x2, y2);

        // snip
    } catch (ExitEarlyException e) {
        // handle early exit
    }
}

private static void click() throws InterruptedException {
    r.mousePress(InputEvent.BUTTON1_DOWN_MASK);
    Thread.sleep(30 + rand.nextInt(50));
    r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
    Thread.sleep(30 + rand.nextInt(50));
}

private static void testPosition(int x2, int y2) throws ExitEarlyException {
    Point p = MouseInfo.getPointerInfo().getLocation();
    if(p.x != x2 || p.y != y2) throw new ExitEarlyException();
}
0 голосов
/ 24 мая 2009

Пусть ваша программа откроет второе окно, которое отображается под вашим главным окном, но развернуто, тогда все ваши ошибочные щелчки мыши будут получены развернутым окном, и он может получить ваш ввод с клавиатуры.

...