2

I'm writing a screen capture utility, and I'd like to be able to store the current state of the keyboard and mouse whenever a screenshot is taken.

Doing this for the mouse is simple, since using the PointerInfo class in a manner described in this related question gives you the screen coordinates for the current mouse location and the click information if desired. However, I haven't been able to find an analog to this class for the keyboard; all the keyboard related classes appear to be focus specific.

So, is there a way to get the current keyboard state in Java?

P.S. Remember that I'm looking for a function to call to retrieve the information regarding what keys are depressed, not a listener for such depression events.

Community
  • 1
  • 1
zergylord
  • 4,368
  • 5
  • 38
  • 60

1 Answers1

6

Something you can do is implement the KeyListener interface and give states to all the keys you're interested in.

If you're interested in checking if the arrow keys are depressed upon a screenshot, for instance, you can implement this KeyListener interface and override keyPressed() and keyReleased() methods and set the state for those keys you are interested in to keyPressed or keyReleased. Depending on the event. That way, when the screenshot occurs, you can just read the state of those keys

If you need this solution to be global, regardless of application focus, you could write a small hook in C that you can integrate with Java Native Interface to listen for key events. Java doesn't let you listen to key events without you attaching the listener to a component and that component having focus. Have a look at JNativeHook.

If you just need it when your application has focus but on every component you could inelegantly attach the listener to all your components or you could write your own custom KeyEventDispatcher and register it on the KeyBoardFocusManager. That way, as long as your application has focus, regardless of component that has specific focus, you could catch all keyboard events. See:

public class YourFrame extends JFrame {    

    public YourFrame() {
        // Finish all your layout and add your components
        //

        // Get the KeyboardFocusManager and register your custom dispatcher
        KeyboardFocusManager m = KeyboardFocusManager.getCurrentKeyboardFocusManager();

        m.addKeyEventDispatcher(new YourDispatcher());
    }

    private class YourDispatcher implements KeyEventDispatcher {
        @Override
        public boolean dispatchKeyEvent(KeyEvent e) {
            if (e.getID() == KeyEvent.KEY_TYPED) {
                // Do something to change the state of the key
            } else if (e.getID() == KeyEvent.KEY_PRESSED) {
                // Do something else
            }
            return false;
        }
    }

    public static void main(String[] args) {
        YourFrame yF = new YourFrame();
        yF.pack();
        yF.setVisible(true);
    }
}
ugo
  • 2,705
  • 2
  • 30
  • 34
  • Thanks for the swift response! I'll try that out now -- sounds like it should work. – zergylord Mar 23 '12 at 21:30
  • Reading the interface makes it sound like this just intercepts keys when a certain Jcomponent has focus, which isn't what I'm looking for. I want to listen for keys pressed *globally* aka regardless of focus. Is there a way for your proposed solution to do this? – zergylord Mar 24 '12 at 06:41
  • I do not think Java will give you that kind of control - ie, implementing a KeyListener regardless of application focus. The best way would be to write a global listener in a language that is closer to the OS you're using, like C. Then use Java Native Interface to integrate with the Key events from C. – ugo Mar 24 '12 at 14:04
  • But if you need to listen for key events only when your Java application has focus, you could add the KeyListener to all components. Very inelegant, I know, but seems to be the only way. – ugo Mar 24 '12 at 14:12