Auf Eingabe ohne Fokus in Java warten

Ich mache ein kleines Programm in Java mit der Robot-class. Das Programm übernimmt die Maus. während des Debuggens, wenn es sich so verhält, dass ich es nicht will, ist es schwer, das Programm zu beenden, da ich die Maus nicht auf die Beenden-Schaltfläche in Eclipse bewegen kann, und ich kann keine Hotkeys verwenden Schlagen Sie es, weil die Maus konstant in ein anderes Fenster klickt und stattdessen dieses Fenster fokussiert.

Ich möchte nur einen Keylistener anschließen, so dass ich, wenn ich q drücke, das Programm beenden kann, aber die einzige Art, wie ich das mache, besteht darin, ein Fenster zu erstellen, und dieses Fenster benötigt Fokus, um die Eingabe zu erfassen. Gibt es eine Möglichkeit, von überall auf Tastatur- oder Mauseingaben zu hören, unabhängig davon, was den Fokus hat?

Dies ist kein triviales Problem und Java bietet Ihnen keine Möglichkeit, es elegant zu machen. Sie können eine Lösung wie banjollity vorschlagen, aber auch das wird nicht immer funktionieren, wenn Ihre irrenden Mausklicks ein anderes volles Fenster öffnen, das gerade in Ihrer Taskleiste geöffnet ist.

Tatsache ist, dass Java den Entwicklern standardmäßig nur sehr wenig Kontrolle über das Betriebssystem gibt. Dies ist auf zwei Hauptgründe zurückzuführen: Sicherheit (wie in der Java-Dokumentation erwähnt) und die Tatsache, dass verschiedene Betriebssysteme Ereignisse völlig unterschiedlich handhaben und ein einheitliches Modell zur Darstellung all dieser erstellen, würden wahrscheinlich keinen Sinn machen.

Also, um Ihre Frage zu beantworten, stelle ich mir vor, was Sie wollen, ist eine Art Verhalten für Ihr Programm, wo es weltweit nach Tastenanschlägen abhört, nicht nur in Ihrer Anwendung. In solch einem Fall müssen Sie auf die functionen Ihres bevorzugten Betriebssystems zugreifen. Um auf Java zugreifen zu können, müssen Sie dies über eine JNI-Schicht (Java Native Interface) tun.

Was du also machen willst ist:

  1. Implementieren Sie ein Programm in C, das auf globale Tastendrücke auf Ihrem Betriebssystem warten wird, wenn dieses Betriebssystem Windows ist, dann suchen Sie nach Dokumentation zu Windows-Hooks, die von Microsoft und MSDN im Web und anderen Orten gut dokumentiert ist. Wenn Ihr Betriebssystem Linux oder Mac OS X ist, müssen Sie mit den X11-Entwicklungsbibliotheken nach globalen Tasten drücken. Dies kann auf einer Ubunutu-Linux-Distribution nach einem Howto geschehen, das ich unter http://ubuntuforums.org/showthread.php?t=864566 geschrieben habe

  2. Verbinden Sie Ihren C-Code über JNI mit Ihrem Java-Code. Dieser Schritt ist eigentlich der leichtere Schritt. Folgen Sie dem Verfahren, das ich in meinem Tutorial unter http://ubuntuforums.org/showthread.php?t=864566 sowohl unter Windows als auch unter Linux verwende, da die Vorgehensweise zum Anschließen Ihres C-Codes an Ihren Java-Code in beiden Betriebssystemen identisch ist.

Die wichtige Sache zu erinnern ist, dass es viel einfacher ist, Ihren JNI-Code zum Laufen zu bringen, wenn Sie zuerst Ihren C / C ++ – Code programmieren und sich vergewissern, dass er funktioniert. Dann ist es einfach, Java zu integrieren.

Es gibt eine Bibliothek, die die harte Arbeit für Sie erledigt: https://github.com/kwhat/jnativehook

Hatte das gleiche Problem. In meinem Fall hat der Roboter nur eine einzige Windows-App gesteuert, die maximiert wurde. Ich habe diese Linien oben auf der Hauptschleife platziert, die den Roboter antreibt:

FarbsymbolCenterColor = new Farbe (255,0,0); // wenn das Programmsymbol rot ist

if (iconCenterColor.equals (robot.getPixelColor (10,15))) triggers eine neue IllegalStateException aus (“Roboter interagiert nicht mit der richtigen App.”);

Um den Roboter abzubrechen, einfach Alt-Tab auf eine andere App. functioniert hervorragend für einen einfachen App-Roboter.

Starten Sie das Programm von einer Befehlszeile in einem Terminal und verwenden Sie Strg-C, um es zu beenden.

Wenn Ihr Programm ein zweites Fenster öffnet, das unterhalb Ihres Hauptfensters angezeigt wird, aber maximiert ist, werden Ihre errorshaften Mausklicks vom maximierten Fenster empfangen und können Ihre Tastatureingabe empfangen.

Hier ist ein reiner Java-Weg, es zu tun, um das Problem zu lösen, das Sie beschrieben haben (nicht das KeyListener-Problem … der Quittungstest früh, wenn Roboterproblem verwendet wird):

Vergleichen Sie während des Tests die Position der Maus mit einer Position, für die der Test kürzlich festgelegt wurde. Wenn es nicht übereinstimmt, beenden Sie den Test. Hinweis: Der wichtige Teil dieses Codes ist die testPosition Methode. Hier ist der Code, den ich kürzlich benutzt habe:

 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(px != x2 || py != y2) throw new ExitEarlyException(); }