Weird behavior of keyboard events in Java - java

When I press "Delete" button on the keyboard, program gets three events - KEY_PRESSED, KEY_TYPED, and KEY_RELEASED. The problem is, in KEY_PRESSED and KEY_RELEASED, parameter "keyCode" is set, but in the KEY_TYPED it is not (in fact, there no meaningful info in that event). With F5 key, it is even funnier - KEY_PRESSED and KEY_RELEASED are registered, but KEY_TYPED never occurs.
The listener was added via Toolkit.getDefaultToolkit().addAWTEventListener(). Using JDK 6.26.
What could be my problem?
EDIT:
Here are the events that happen when Delete key is pressed:
java.awt.event.KeyEvent[KEY_PRESSED,keyCode=127,keyText=Delete,keyChar=Delete,keyLocation=KEY_LOCATION_STANDARD,rawCode=119,primaryLevelUnicode=127,scancode=0] on javax.swing.JButton[,0,0,61x30,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.synth.SynthBorder#50f38cf0,flags=288,maximumSize=,minimumSize=,preferredSize=,defaultIcon=javax.swing.ImageIcon#6ae2d0b2,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=0,left=0,bottom=0,right=0],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=SVG,defaultCapable=false]
java.awt.event.KeyEvent[KEY_TYPED,keyCode=0,keyText=Unknown keyCode: 0x0,keyChar=Delete,keyLocation=KEY_LOCATION_UNKNOWN,rawCode=0,primaryLevelUnicode=127,scancode=0] on javax.swing.JButton[,0,0,61x30,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.synth.SynthBorder#50f38cf0,flags=288,maximumSize=,minimumSize=,preferredSize=,defaultIcon=javax.swing.ImageIcon#6ae2d0b2,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=0,left=0,bottom=0,right=0],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=SVG,defaultCapable=false]
java.awt.event.KeyEvent[KEY_RELEASED,keyCode=127,keyText=Delete,keyChar=Delete,keyLocation=KEY_LOCATION_STANDARD,rawCode=119,primaryLevelUnicode=127,scancode=0] on javax.swing.JButton[,0,0,61x30,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.synth.SynthBorder#50f38cf0,flags=288,maximumSize=,minimumSize=,preferredSize=,defaultIcon=javax.swing.ImageIcon#6ae2d0b2,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=0,left=0,bottom=0,right=0],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=SVG,defaultCapable=false]

better would be implements KeyBindings
part of keyboard are reserved Keys for built-in JComponent funcionality, more informations from #camickrs UIManager Defaults
depends of reason(s) why you needed implents KeyListener, because for there are lots of another Listeners for various JComponent, that should be filtering or register text changes inside
some of JComponent Models generated Events from Mouse and Keyboard input

From the JavaDoc The "key typed" event. This event is generated when a character is entered. In the simplest case, it is produced by a single key press. Often, however, characters are produced by series of key presses, and the mapping from key pressed events to key typed events may be many-to-one or many-to-many.
You are trying to get the F5 key which is probably not registered as a character being entered. By using the KEY_RELEASED you will consistently get the result you are looking for and the API is behaving as expected.

Key typed events ALWAYS generate '0' as the key code. Look up the method getKeyChar() instead, or (as has been suggested) listen for keyReleased() instead.
getKeyChar(): http://goo.gl/ajH03

Related

Java Keypressed event on netbeans gui does not work?

I use Netbeans form template to build gui and add Keypress event on form(right-click > Event > KeyPressed) like a code below.
But it seems System.out.print or another action does not perform anything.
So how should I do to fix this problem?
private void formKeyPressed(java.awt.event.KeyEvent evt) {
char PressedChar = evt.getKeyChar();
System.out.print(PressedChar);
}
So how should I do to fix this problem?
Swing is designed to be used with Key bindings which is a more flexible and reliable approach that brings with these benefits:
Separates the action itself from the key strokes.
There are different conditions to trigger those actions: WHEN_FOCUSED, WHEN_IN_FOCUSED_WINDOW, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
We can take advantage of those conditions to attach different actions to different components relying on a precedence-based policy (see the example presented here).
Having said this, we'd rarely want to listen for any key pressed to do something but for some specific key stroke or key combination in order to perform some action. However if your use case is such then yes, you'll need a KeyListener, but please take a look to this answer by #camickr to do it correctly.
See also this topic: Key bindings vs. key listeners in Java, and How to Use Key Bindings tutorial

Capturing specific keystrokes in Java Swing

There are a lot of topics on how to capture keystrokes in Java Swing, but I'd like to ask about the best practice. For example, I have a window in which I wish to listen to a keystroke of either F1 or Command-P on a Mac (or CTRL-P on a PC).
Reading The official Javadoc for KeyEvent, it seems that it is a better practice to use Key Typed events rather than Key Pressed or Key Released events, because they are higher-level. This makes sense to me, and I've even found that in order to make sure the program is platform-agnostic, I have to specify a keystroke object thusly:
private KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_P, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
This should allow for capturing of either the Command accelerator key on a Mac, and the CTRL accelerator key on a PC. (I hope I'm using those terms correctly.) So now that I have a KeyStroke object, how do I go about checking it against a KeyEvent object in my KeyListener? And throwing a check for an F1 key event as well only complicates the matter further, though hopefully not too much.
Suggestions?
So now that I have a KeyStroke object, how do I go about checking it against a KeyEvent object in my KeyListener?
You don't use a KeyListener. Swing was designed to be used with Key Bindings.
Check out Key Bindings which contains a program to list the default bindings of each Swing component. It also give some example of how you might create your own ey Bindings. It also contains a link to the Swing tutorial on Key Bindings which explains the whole process in more detail

Java KeyEvent: how to read in two keys at once

I am making a simple game(my first time using key reader) and am using WASD inputs to move the character. I want to make it so that if you press, say, W and A at the same time, you go diagonal. Does anyone know how to do this?
Don't use a KeyListener. Swing was designed to be used with Key Bindings.
Either way you can't listen for multiple keys at once so you need to keep track of which keys have been pressed. Since you want to do animation you would generally use a Swing Timer to schedule the animation. Then every time the Timer fires you check which keys are pressed and move you character based on the keys pressed.
Check out KeyboardAnimation.java source code from Motion Using The Keyboard for an example that demonstrates this approach. This article also gives reasons why key bindings are preferred over a KeyListener.

Java Swing: Key pressed key stroke on an `InputMap` triggers its action several times while holding down the key

I register
getInputMap().put(KeyStroke.getKeyStroke("pressed RIGHT"), "go right");
When testing the code I get: While I hold the right arrow key down, the action is triggered repeatedly and not only once as I would have expected this.
Interestingly
getInputMap().put(KeyStroke.getKeyStroke("released RIGHT"), "stop");
triggers stop only when the key is finally released.
Is there a way to register a key stroke on an input map, so that the associated action is only triggered once at the moment when the key is pressed?
Documentation of KeyStroke:
A KeyStroke represents a key action on the keyboard, or equivalent
input device. KeyStrokes can correspond to only a press or release of
a particular key, just as KEY_PRESSED and KEY_RELEASED KeyEvents do;
alternately, they can correspond to typing a specific Java character,
just as KEY_TYPED KeyEvents do. In all cases, KeyStrokes can specify
modifiers (alt, shift, control, meta, altGraph, or a combination
thereof) which must be present during the action for an exact match.
To trigger the event only once, at release time, I suggest to register
getInputMap().put(KeyStroke.getKeyStroke("typed RIGHT"), "go right");
The documentation of KeyStroke.getKeyStroke(String) is:
Parses a string and returns a KeyStroke. The string must have the
following syntax:
modifiers* (typedID | pressedReleasedID)
modifiers := shift | control | ctrl | meta | alt | altGraph
typedID := typed <typedKey>
typedKey := string of length 1 giving Unicode character.
pressedReleasedID := (pressed | released) key
key := KeyEvent key code name, i.e. the name following "VK_".
To trigger the event only once, at press time, I suggest to register the press and release events to manage yourself a latch with a boolean.
Is there a way to register a key stroke on an input map, so that the associated action is only triggered once at the moment when the key is pressed?
Remove the keyPressed binding from the InputMap. Then for the keyReleased Action you add the keyPressed binding back to the InputMap.
However, even this can cause problems because on a Windows OS the sequence of KeyEvents is:
pressed, pressed, pressed.... released.
This makes sense to me as generally when you hold the key down you want the character to repeat. However, on a Mac I believe the sequence is:
pressed, released, pressed, released, pressed, released
which doesn't make sense to me and makes it difficult to determine when a key has truly been released.
The "key typed" event operates per platform behaviour -- which, as standard since before the 1980's, has always included auto-repeat. This would be driven by the low-level events from the OS.
You could try not holding down the keys? You shouldn't be mashing the keyboard, it's a precision instrument.
You can possibly change the key-stroke binding (to avoid receiving auto-repeat) or otherwise use a custom event-listener & handle only the low-level keydown/ keyup event once. Low-level events may however expose keycodes (as they are below the level of actually typing any one character) rather than characters.

SWT: KeyPressed Event After Done

I'm creating a text box that automatically completes the input from a list. For example, if you enter 345, it might check the list and find 345678, and then the text box has 345, and then 678 highlighted.
http://nucleussystems.com/files/Screenshot.png
This way, if you continue typing something different, it removes the automatically appended text.
I tried doing it with the keyReleased event, but there were user experience problems if more than one key was pressed at a time (something very common when typing fast). But I soon found out that the keyPressed event doesn't add the text typed until after the event handler(s) is/are called.
So I need to find out a way to fire my event handler after SWT has handled it. Is this possible?
I think SWT.Modify event can provide what you need. Have a look at the ModifyListener documentation.

Categories

Resources