Capturing specific keystrokes in Java Swing - java

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

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

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 InputEvent modifiers for various hardware

I am looking for a list of (hardware) modifier keys and their mapping to masks in the Java Swing interface InputEvent. As Java 7, there are five masks I know about:
SHIFT_DOWN_MASK
CTRL_DOWN_MASK
META_DOWN_MASK
See wiki.
ALT_DOWN_MASK
ALT_GRAPH_DOWN_MASK
See: wiki.
Please kindly draw my attention if I am missing any.
From this Eclipse bug report about SWT, I learned:
Apple machines tend to have four keys: command, option, shift and control.
PC-style machines tend to have five keys (nowadays): control, alt, shift, win,
and menu.
For this discussion, I do not consider the menu key a modifier. (Again: Correct me if wrong.)
However, win key can be used in combination, e.g., Win+E to open a new window for Windows Explorer.
I realize the line between "PC" and "Apple" has blurred in the past few years. It may be possible to have keyboards with a plethora of modifiers.
My questions:
How does the Apple command and option keys map to InputEvent masks?
How does the PC win key map to InputEvent masks?
"Shortcut" or "Accelerator" keys are easily handled in a cross- platform way
in Swing.
The Toolkit gives the key ID for the native OS shortcut key:
int shortcut = Toolkit.getDefaultToolkit ().getMenuShortcutKeyMask();
With this you can make a KeyStroke
int key = KeyEvent.VK_Q; // or whatever
KeyStroke ks = KeyStroke.getKeyStroke( key, shortcut );
The method getMenuShortcutKeyMask is the correct, cross-platform, Sun- supported way of obtaining the appropriate modifier mask for menu accelerators (AKA shortcuts) for the current platform. It returns a modifier mask using the appropriate java.awt.event.InputEvent constants for the current platform -- on OS X this is InputEvent.META_MASK, on Windows it is InputEvent.CTRL_MASK. Using these literals instead of calling getMenuShortcutKeyMask is bad form, although it works.
One additional thing to note is that you can use combinations of modifiers in accelerator keystrokes:
KeyStroke ks = KeyStroke.getKeyStroke( KeyEvent.VK_P, shortcut | InputEvent.SHIFT_MASK );
to create a Command+Shift+P keystroke (on OS X, Control+Shift+P on Windows). This allows you to create accelerator keystrokes using mnemonic keys that are used by standard menu items (e.g. Print, which uses Command+P) without conflicting with the standard keystrokes.
In the case of Windows key:
// Invoked when a key has been pressed.
public void keyPressed(KeyEvent e) {
// Returns the integer code for the key on the keyboard and if
// keyCode is equal to VK_WINDOWS)...
if (e.getKeyCode() == KeyEvent.VK_WINDOWS) {
// ...call the doIT method.
doIT();
}
}

Weird behavior of keyboard events in 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

Java - Key Events and Key Binds

Is it possible to bind a global key listener for a Java program?
Like windows key binds.
My objective is to when I am in a game, I could, for example, change my current music by pushing F2 or F3.
See the answer for Java System-Wide Keyboard Shortcut. If you want it to apply globally (and not just when the container is minimized), then this should do it. If you want it only for when your container is minimized, then you can take that solution and see if your container is minimized (Frame.getState()).

Categories

Resources