Working on a new personal project with jframe. My goal is to close the frame in an ActionListener to the background, and when specific keys are pressed (Ctrl+
Well, the problem is that java is designed to be platform independent. Too achieve that, there have to be some limitations for the programms written in this programming language. You want to capture keystrokes even if your window/programm doesn't have the focus set on it. In fact what you need to write is some kind of global keylistener. You can't do such things in java. In fact you have to choose a much more machine-oriented programming language like c/c++ to achieve what you want.
In java such stuff is only possible using the Java Native Interface (short JNI). Using JNI it is possible to write a library for hooking the keyevents in for example c/c++ and call the librarys' methods using a java programm.
JNativeHook ( https://github.com/kwhat/jnativehook ) is using this exact approach. But well, i haven't tried this framework so i can't tell if it's working.
But i once used this and it worked fine for me: http://softk.de/opensource/jglobalkeylistener.html
You can just download the source and don't panic even if the site is written in german, the source-code is documented in english and even the comments within the code are in english.
PS: if that doesn't work, it may help you to google for things like "java global keylogger", because thats exactly what a keylogger is doing (well it obviously also logs the keys) and i think there will be much more stuff that may help you.
Greetings, Loki
- Is this the best way to do it? I'm trying to keep the CPU usage as low as possible.
As previously mentioned, use JNativeHook. It is the only cross-platform solution and it will be much faster and less intensive than a polling approach like while (1) { GetAsyncKeyState(...); Sleep(5); }
The biggest performance bottleneck with JNativeHook is the OS, not the library.
- Will the ActionListener even work while the frame's not visible?
It will not work unless the frame has focus, but the native library will provide other events that do fire out of focus, so you could make it work by fabricating your own ActionEvent's from the NativeInputEvent listeners. Just make sure you set the library to use the Swing event dispatcher as it does not by default!
- How do I listen to multiple key presses? I have an idea but it doesn't sound like it will work.
What do you mean by "multiple key presses?" If you mean auto-repeat when a key is held down, that is handled by sending multiple Key Pressed events after the auto repeat delay is exceeded at an interval of the auto repeat rate. You many also receive multiple Key Typed events if that event produces a printable character. When the key is released, a single key release event will be dispatched. If you mean a sequence of keys or multiple keys at the same time, you will need to do your own tracking or checks in the native input listener, but it should be possible.
Basic Modifier Example: Note that JNativeHook library has both a left and right mask for the modifier keys. I assume you want to use a combination of either the left or the right which makes this a tad more complicated.
public void nativeKeyPressed(NativeKeyEvent e) {
// If the keycode is L
if (e.getKeyCode() == NativeKeyEvent.VK_L) {
// We have a shift mask and a control mask for either the left or right key.
if (e.getModifiers() & NativeInputEvent.SHIFT_MASK && e.getModifiers() & NativeInputEvent.CTRL_MASK) {
// Make sure you don't have extra modifiers like the meta key.
if (e.getModifiers() & ~(NativeInputEvent.SHIFT_MASK | NativeInputEvent.CTRL_MASK) == 0x00) {
....
}
}
}
}