2009-05-23 19 views
19

Estoy haciendo un pequeño programa en Java usando la clase Robot. El programa toma el control del mouse. mientras estoy depurando si comienza a actuar de una manera que no quiero que sea difícil salir del programa, ya que no puedo mover el mouse hasta el botón de terminar en eclipse, y no puedo usar las teclas rápidas para golpéelo porque el mouse está constantemente haciendo clic en otra ventana, dando ese foco de ventana en su lugar.Escuchando por entrada sin foco en Java

Lo que me gustaría hacer es simplemente conectar un keylistener para que cuando presiono q pueda salir del programa, pero la única manera en que sé cómo hacer esto implica hacer una ventana, y esa ventana debe enfocarse en captura la entrada. ¿Hay alguna manera de escuchar la entrada del teclado o el mouse desde cualquier lugar, independientemente de lo que tenga foco?

Respuesta

13

Esto no es un problema trivial y Java no le da una manera de hacerlo elegantemente. Puede utilizar una solución como banjollity sugerida, pero incluso eso no funcionará todo el tiempo si su mouse errante hace clic para abrir otra ventana de tamaño completo actualmente abierta en su barra de tareas, por ejemplo.

El hecho es que Java da a los desarrolladores muy poco control sobre el sistema operativo. Esto se debe a dos razones principales: la seguridad (como lo indica la documentación de Java) y el hecho de que diferentes sistemas operativos manejan los eventos de forma completamente diferente y hacer que un modelo unificado para representar todos estos no tenga mucho sentido.

Así que, para responder a su pregunta, me imagino que lo que quiere es algún tipo de comportamiento para su programa en el que escucha las pulsaciones de teclas globalmente, no solo en su aplicación. Algo así requerirá que acceda a la funcionalidad ofrecida por su sistema operativo de su elección, y para acceder a ella en Java necesitará hacerlo a través de una capa Java Native Interface (JNI).

Así que lo que quiere hacer es:

  1. implementar un programa en C que va a escuchar las pulsaciones de teclas globales de su sistema operativo, si este sistema operativo es Windows que busque la documentación en Windows ganchos que es bien docuemented por Microsoft y MSDN en la web y en otros lugares. Si su sistema operativo es Linux o Mac OS X, tendrá que escuchar las pulsaciones de tecla globales utilizando las bibliotecas de desarrollo X11. Esto se puede hacer en una distribución ubunutu linux según un Howto que escribí en http://ubuntuforums.org/showthread.php?t=864566

  2. Conecta tu código C a tu código Java a través de JNI. Este paso es realmente el paso más fácil. Siga el procedimiento que uso en mi tutorial en http://ubuntuforums.org/showthread.php?t=864566 en Windows y Linux, ya que el procedimiento para conectar su código C a su código Java será idéntico en ambos sistemas operativos.

Lo importante a recordar es que es mucho más fácil para obtener su código JNI de funcionar si el primer código y depurar la C/C++ de código y asegurarse de que se está trabajando. Entonces, integrarlo con Java es fácil.

+0

¿Se puede hacer esto con maldiciones java? http://sourceforge.net/projects/javacurses/ – RadijatoR

0

Inicie el programa desde una línea de comando en un terminal y use Ctrl-C para terminarlo.

+0

En mi opinión, esta es la respuesta correcta. La pregunta establece que es solo para la depuración y esto no requiere ningún cambio en el código. – user2623008

0

Haga que su programa abra una segunda ventana que se muestra debajo de su ventana principal pero está maximizada, luego sus clics de mouse errantes serán recibidos por la ventana maximizada, y puede recibir su entrada de teclado.

1

Tenía el mismo problema. En mi caso, el robot solo controló una sola aplicación de Windows, que se maximizó.Coloqué estas líneas en la parte superior del lazo principal que impulsa el robot:

Color iconCenterColor = new Color (255,0,0); // si el ícono del programa es rojo

if (iconCenterColor.equals (robot.getPixelColor (10,15))) lanza la nueva IllegalStateException ("el robot no interactúa con la aplicación correcta.");

Para cancelar el robot, simplemente alt-tab a otra aplicación. Funciona muy bien para un simple robot de manejo de una aplicación.

+0

Olvidé negar la prueba. Entonces funciona genial: – user467317

17

hay una biblioteca que hace el trabajo duro para usted: https://github.com/kwhat/jnativehook

+0

Esta respuesta debe marcarse la correcta. Obviamente, el ecosistema de Java proporciona una manera fácil de hacerlo elegantemente. –

+1

@ CollinBell Esa biblioteca usa la metodología nativa de cada sistema operativo para llevar a cabo dicha tarea. Hay otras bibliotecas que hacen algo similar. Creo que es inexacto decir que el ecosistema de Java ofrece una manera fácil de hacerlo. Alguien ha hecho todo lo posible para crear una biblioteca de terceros para llevar a cabo esta tarea, no forma parte de ningún paquete estándar de Java. – ldog

+1

@Idog Una biblioteca es parte del ecosistema. La principal preocupación que tengo es "¿se puede hacer sin que yo escriba ningún código de bajo nivel?" y la respuesta a eso es sí (ish). Lo sé porque utilicé esta lib (aunque había un error en el código c subyacente que tuve que arreglar y enviar una solicitud de extracción). –

0

He aquí una forma pura de Java para hacerlo para resolver el problema que usted ha descrito (no el problema KeyListener ... la prueba de dejar de fumar a principios cuando se usa el problema del robot):

A lo largo de la prueba, compare la posición del mouse con una que su prueba haya configurado recientemente. Si no coincide, abandone la prueba. Nota: la parte importante de este código es el método testPosition. Aquí está el código que utilicé recientemente:

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(); 
} 
Cuestiones relacionadas