I'm trying to automate some processes using Robot and it seems certain keycodes (only symbols that require you to hold shift when typing it normally) in KeyEvent are throwing an IllegalArgumentException. This is all the code that's running in main:
Robot r = new Robot();
r.keyPress(KeyEvent.VK_EXCLAMATION_MARK);
However, it works fine using the following workaround:
Robot r = new Robot();
r.keyPress(KeyEvent.VK_SHIFT);
r.keyPress(KeyEvent.VK_1);
Any ideas why the exception is thrown? Thanks!
Java version: 1.6.0_23
Because like the documentation for Robot.keyPress says, an IllegalArgumentException is thrown when the keycode doesn't represent a valid key, and VK_EXCLAMATION_MARK is not a valid key.
Keycodes are used to represent two things: keys on the keyboard, and "a character was typed" events. Typing a character often requires more than one keypress (in sequence, or simultaneously, or both). But Robot.keyPress simulates the act of pressing a key (hence the name), not the act of typing a character.
For more information, see the documentation for KeyEvent: http://download.oracle.com/javase/6/docs/api/java/awt/event/KeyEvent.html
I don't know Robot, but isn't that because it needs to be two keys pressed to an exclamation mark to be inserted.
There are no exclamation mark key on the keyboards.
Related
Background
Operating systems (I'm on Windows 10, if it matters) have a feature called Mouse Keys that allow you to perform the operations of the mouse using the numpad. Press 5 to click, 8/2/4/6 to move the cursor up/down/left/right, and so on.
The Desire
I would like to move the cursor around when Mouse Keys is activated, programmatically, in Java. I specifically want to use keyboard events for this, as moving the mouse directly is verboten in the context I'm in.
The Problem
I tried using Robot.keyPress and Robot.keyRelease with keycode KeyEvent.VK_KP_UP = 224, but that yields the following error:
java.lang.IllegalArgumentException: Invalid key code
at java.desktop/sun.awt.windows.WRobotPeer.keyPress(Native Method)
at java.desktop/java.awt.Robot.keyPress(Robot.java:350)
And trying it with KeyEvent.VK_NUMPAD8 doesn't error out, but also doesn't make the mouse move.
I also tried jnativehook's GlobalScreen.postNativeEvent(new NativeKeyEvent(...)), and no amount of voodoo could get it to work either. There's no constant in NativeKeyEvent for the keypad up key, so that's not super surprising. When I try to send the keycode 224, the following error occurs:
com.github.kwhat.jnativehook.GlobalScreen postNativeEvent
WARNING: map_keyboard_event [97]: Unable to lookup scancode: 224
Am I asking the impossible?
I'm currently working on the input system of a game engine in java, and I use GLFW for the window. I set up a callback system to catch when a key is pressed:
GLFW.glfwSetKeyCallback(window, (windowId, key, scancode, action, mods) -> {
if (action == GLFW.GLFW_PRESS) {
System.out.println(GLFW.glfwGetKeyName(key, scancode));
}
});
And the problem is when I press space or enter or shift plus a different key it prints out null. My question is: how to use the mods attribute to capitalize the next key when I press shift or print out a new line when I press enter etc.
I don't know the solution for the first question, but the second one is easy.
Try using char callback. This one is different from key callback, as it only works with unicode characters being typed by user (letters are capitalized with Shift, CapsLock button also works). Also, if you want to detect modifier buttons being pressed while user types, try using charMods callback. Seems like the latter is marked for removal, so you can test whether the modifier button is pressed with glfwGetKey().
EDIT: Seems like I didn't understood you on the first one. glfwGetKeyName() is not designed to be used as text input method. Also note that it can display names for a limited range of buttons. What is more, when you press multiple keys, press event for each one is called in separate key callback event. You can't handle multiple key presses at once. (Modifier keys are put in mods argument of callback, but I can't tell by now whether they also trigger a key press event or not - check it yourself)
In a swing program I am trying to receive input specifically from the num pad keys on the keyboard using key bindings.
myPanel.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_NUMPAD8, 0), “numpad8”);
myPanel.getActionMap().put(“numpad8”, numPad8);
Works fine if I got the num lock on, which is as expected, however if I add:
myPanel.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_KP_UP, 0), “numpad8”);
Without num lock on, my keyboard does not cause numPad8 Action to be called (in fact it seems to generate KeyEvent.VK_UP instead). This is surprising to me as the documentation of KeyEvent specifies that KeyEvent.VK_UP is
Constant for the non-numpad up arrow key.
and KeyEvent.VK_KP_UP
Constant for the numeric keypad up arrow key.
So my question is: If I want my code to support as many keyboard set ups as possible what KeyEvents should I expect from the num pad? Should I add KeyEvent.VK_8 to the above just be safe, for example?
I am trying to simulate keyboard input by programmatically generating KeyEvent objects and pumping them to the event queue. This works fine except that when characters are being entered into a JTextField, for example, the cursor (caret?) does not move to always be at the end of the entered value. For example, if we denote the caret as the pipe | then this is what I get:
An 'A' keypress is simulated by sending a KEY_PRESSED, KEY_TYPED, KEY_RELEASED event, and the JTextField value is:
|A
that is, the cursor/caret is back at the beginning of the field after the A is entered.
How do I get the cursor/caret to automatically move as it would when actual physical keys are pressed?
Have you tried using the Robot Class in the JDK?
http://docs.oracle.com/javase/6/docs/api/java/awt/Robot.html
After you issue each command, call a method that uses setCaretPosition() to the end of the text in the JTextField. This will be much easier if you use a J*Pane so you can call getDocument() and you will have much more control.
I am using keyboard_key variable from here:
//overrides the function keyPressed from "lcdui.Canvas"
protected void keyPressed(int keyCode){
keyboard_key = keyCode;
}
to detect if any key was pressed on a mobile phone.
But it returns only the key that is pressed most lately and it doesn't tell if any other key might be pressed. Please help!
Btw, I'm using NetBeans 7.0.1 as IDE.
...it returns only the key that is pressed most lately and it doesn't tell if any other key might be pressed
The way you use it in your code snippet, keyboard_key will always contain only the key that is pressed most lately - just because it "has no room" to hold anything more than that.
Consider using Vector to "memorize" different keys that were pressed.
//define in your class:
Vector keysPressed = new Vector(); // to keep track of keys pressed
//overrides the function keyPressed from "lcdui.Canvas"
protected void keyPressed(int keyCode){
keysPressed.addElement(new Integer(keyCode));
}
Side note given the question, you may benefit from studying Java language basics. There are many tutorials available online - just search the web for something like "Java getting started".
Depending on your application requirements, consider overriding keyRepeated along with keyPressed.
If you intend to handle key presses in game-loop fashion ("multiple keys at once" suggest that you may possibly have this in mind), consider another option provided by lcdui.game.GameCanvas API, method getKeyStates():
Gets the states of the physical game keys. Each bit in the returned integer represents a specific key on the device. A key's bit will be 1 if the key is currently down or has been pressed at least once since the last time this method was called. The bit will be 0 if the key is currently up and has not been pressed at all since the last time this method was called. This latching behavior ensures that a rapid key press and release will always be caught by the game loop, regardless of how slowly the loop runs...