Приостановить выполнение потока и возобновить на основе пользовательского ввода

У меня есть поток, который стимулирует JNativeHook.jar, который создает глобальный слушатель клавиатуры и мыши. На основе пользовательского ввода поток может действовать как таковой.

Я хотел бы остановить выполнение всех потоков, когда пользователь (скажем, нажимает VK_SPACE). Я хотел бы создать другой поток, который также следит за клавиатурой, и когда он снова получает VK_SPACE, он сообщит основному потоку о возобновлении.

Возможно ли такое действие в Java и как оно может выглядеть?

Вот код для работы с JNativeHook.jar

КОД:

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

public class GlobalKeyListenerExample implements NativeKeyListener 
{
public void nativeKeyPressed(NativeKeyEvent e) 
{
    System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));

    if (e.getKeyCode() == NativeKeyEvent.VK_ESCAPE) 
    {
        GlobalScreen.unregisterNativeHook();
    }
    if (e.getKeyCode() == NativeKeyEvent.VK_SPACE) 
    {
            WatchForMe w = new WatchForMe(this);
            w.start();
            this.wait();
    }
}

public void nativeKeyReleased(NativeKeyEvent e){}
public void nativeKeyTyped(NativeKeyEvent e){}

public static void main(String[] args) 
{
    try 
    {
        GlobalScreen.registerNativeHook();
    }
    catch (NativeHookException ex) 
    {
        System.err.println("There was a problem registering the native hook.");
        System.exit(1);
    }

    //Construct the example object and initialze native hook.
    GlobalScreen.getInstance().addNativeKeyListener(new GlobalKeyListenerExample());
}
}

public class WatchForMe implements NativeKeyListener 
{
boolean alive = true;
Thread me = null;
public WatchForMe(Thread me)
{
    if(me == null) return;
    this.me = me;
    GlobalScreen.getInstance().addNativeKeyListener(this);
}
public void nativeKeyPressed(NativeKeyEvent e) 
{
        System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
        if (e.getKeyCode() == NativeKeyEvent.VK_SPACE) 
        {
                me.notify(); 
                alive = false;
        }
}
 public void run()
 {
     while(alive){}
 }

public void nativeKeyReleased(NativeKeyEvent e){}
public void nativeKeyTyped(NativeKeyEvent e){}
}

2 ответа

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

Проблема, с которой вы сталкиваетесь в настоящее время, заключается в том, что вы знаете, 1) в каком потоке вы находитесь и какой эффект "паузы" может иметь, и 2- знаете, когда возникает комбинация "un-pause"... потому что вы больше не слушаете ключевые события (потому что вы могли случайно остановить поток, который использовался нативным интерфейсом для вызова событий с...)

public void nativeKeyPressed(NativeKeyEvent e) 
{
    System.out.println("Key Pressed: " + NativeKeyEvent.getKeyText(e.getKeyCode()));

    if (isPaused) {
        if (e.getKeyCode == UNPAUSE_KEY_CODE) { 
            isPaused = false;
        }
    } else {
        if (e.getKeyCode == PAUSE_KEY_CODE) { 
            isPaused = true;
        } else {
            // Handle other key strokes...
        }
    }
}

обновленный

Как примечание... это

public void run()
{
    while(alive){}
}

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

В методе выполнения:

public void run(){
 while(me!=null) //execute forever
   try{
      Thread.sleep(5);
      if(!alive) continue; //define pause

      ... do somthing   
   catch(Exception e){}

Нам нужно "нарезать" все время, проверяя, есть ли эта "пауза".

Важный! рекомендуется использовать метод public synchronized void setAlive (boolean value) чтобы избежать конфликтов "нить"

Другие вопросы по тегам