KeyEvent.getKeyText() on mac

Hi!

I’m using KeyEvent.getkeyText() to return a string representation of a keycode in a game I’m making. For example, the keycode for enter should be translated to the string “Enter”. This applies to space, shift, cmd and similar keys as well.

This works on windows machines, but not in osx for some reason.

KeyEvent.getKeyText(32); returns “?” on macs and “Space” on windows machines.

Help?

What does Toolkit.getProperty(“AWT.space”, “Space”); return on your Mac?

Also, what OSX and Java version are you using?

Don’t use magic numbers. First, constants are usually defined for good reason. Their values could vary between different platforms to reflect the differences in those platforms and are there to enable better coding practices. Using constants instead of magic numbers ensures that your code is cross platform and forwards compatible with new Java versions. Second, key codes are not equivalent to characters. The return value of that function is also dependent on the user’s platform, keyboard, and language. Try KeyEvent.getKeyText(KeyEvent.VK_SPACE).

[quote]“Key pressed” and “key released” events are lower-level and depend on the platform and keyboard layout. They are generated whenever a key is pressed or released, and are the only way to find out about keys that don’t generate character input (e.g., action keys, modifier keys, etc.). The key being pressed or released is indicated by the getKeyCode method, which returns a virtual key code.

Virtual key codes are used to report which keyboard key has been pressed, rather than a character generated by the combination of one or more keystrokes (such as “A”, which comes from shift and “a”).
[/quote]

[quote]public static String getKeyText(int keyCode)

Returns a String describing the keyCode, such as "HOME", "F1" or "A". These strings can be localized by changing the awt.properties file.

Returns:
    a string containing a text description for a physical key, identified by its keyCode

[/quote]

VK_SPACE has always, is always, and will always be 32. OP might be from another language where 32 is commonly used so it’s fine for this case.

Also, the KeyEvent keycodes for 0-9 and A-Z do correspond to their ASCII counterparts.

On Mac, KeyEvent.getKeyText should return the unicode character (e.g. “\u2318” for the command symbol) for proper use with menu items and accelerators. I can confirm that VK_META returns “\u2318” on my Mac, which is then printed to the console as ‘?’. VK_SPACE also turns into a ‘?’.

It’s pretty useless for debugging and practical purposes, though… Especially games with limited character sets for their bitmap fonts.

Since there are so many keys that would be displayed as “?” on Mac (alt, control, shift, escape, tab, left, up, etc) I would suggest rolling your own KeyEvent-to-text, e.g.
http://www.java-gaming.org/?action=pastebin&id=247

(Ideally much of that would be put into a properties file for localization…)

[quote]VK_SPACE has always, is always, and will always be 32. OP might be from another language where 32 is commonly used so it’s fine for this case.

Also, the KeyEvent keycodes for 0-9 and A-Z do correspond to their ASCII counterparts.
[/quote]
As stated in the KeyEvent javadocs:

WARNING: Aside from those keys that are defined by the Java language (VK_ENTER, VK_BACK_SPACE, and VK_TAB), do not rely on the values of the VK_ constants. Sun reserves the right to change these values as needed to accomodate a wider range of keyboards in the future.

I was afraid someone would call me out on something I said because I was too lazy to hunt down the details, but I can’t believe I missed the warning message. Now that I found it by using ?+F I am surprised I missed something in plain sight. :wink: (Still, magic numbers in that type of context are evil.) I wonder what the justification behind single character key text Strings could have been. That and what program used an ASCII replacement character for unknown Unicode characters.

Funny thing that those constants are ‘burnt’ into the classfiles, instead of looked up at runtime. So if you were to use the constant VK_SPACE years ago, the very same classfile/jar would contain a constant not equal to VK_SPACE.

The VK_* fields on KeyEvent are not final, so they could in fact be changed. Still, the odds of that happening, especially now, are vanishingly small.

[quote=“Riven,post:7,topic:39578”]
I did not follow that. That seems self contradictory. Wouldn’t “burnt into” mean something was made permanent?

Maybe you’re confused. There are constants baked into the class at compile time, but all those VK_THINGS are static variables. When the class is loaded at run time, they get their default values, which are defined by an offset to a class file constant. By the time your code gets access to them, they all store the correct values. I guess they could get changed since they’re not final, but assuming nothing loads, unloads, and reloads the class and no Java code, outside code, bugs, or solar flares change them, then they’re going to stay the same at run time. And unless the class gets recompiled or otherwise updated, then their default values should stay the same between executions, too. Magic numbers, on the other hand, do have that exact problem because you’re loading them from MyClass.class instead of KeyEvent.class.

@oByhring

Did you mean this character � ? As in “\uFFFD”. I read “?” as a String literal instead of plain English. ::slight_smile:

No they’re not, they are final. All references to them by javac will be dereferenced at compile time and the constants baked in to the resulting classfiles. Being public static final, Oracle cannot change them now as they are part of the API contract and it would cause major breakage.

Cas :slight_smile:

[quote=“Best_Username_Ever,post:9,topic:39578”]
Like I said in my last post, it prints a question mark character: ‘?’. This is how Mac Terminal displays unicode strings and special characters; there is probably a switch somewhere to enable a wider range of unicode glyphs.

Since getKeyText is localized to the user’s AWT properties (i.e. instead of “Shift” or “Enter” as on Windows, it returns a unicode symbol for Mac), it’s pretty useless for debugging and other practical purposes. Which is why I’d suggest rolling your own if you’re expecting plain text.

http://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyEvent.html#VK_1

I don’t see ‘final’.

Edit. Oh f**k me. Javadoc just left it out. You have to click on a totally separate section to see that they’re final.

Please tell me you’re being sarcastic…I can clearly see them >.>

EDIT: LOL!

The ‘final’ doesn’t show up in the Field Summary, only on the field itself. Piece of crap javadoc.

That’s ridiculous. Even if a symbol was a good idea for avoiding localization problems they should have at least supported it in their own programs and provide a fallback glyph for all their built in fonts. >:(

It’s too bad they didn’t provide useful localization. You should be able to use a function intended for localization support with other localization functions. For example displaying native and translated versions of the phrase "press the key to do ". Or, for example, telling the user the name of the keys currently configured in a key binding editor. :clue:

Thanks for all the replies everyone :slight_smile:

This is exactly what I am doing.

I’ve been developing this game for the windows platform the entire time, and I’m just doing the finishing touches on the mac export now.

If I understood you all correctly, what I need to do is make my own method for translating keycodes to text?

Something like this:

if(keycode == KeyEvent.VK_SPACE){
return “Space”;
}
else {…

for the most relevant keys (Space, Enter, Shift, CMD, Alt++?

You could write a function like isBadKeyText(s) that takes a String and returns true if it contains only private use characters or non-printable glyph. Then you can either write your own translations, use reflection to get the English/Java name, or hardcode a default name in one language. You could also use the isBadKeyText(s) method to decide how to display a key as a fallback on platforms like that. For example you could try writing “� (Space)”, “� 32” (key number), or “Special Key #32”.

Just use the code I posted earlier. It will give you printable text based on the VK_XX field name (e.g. VK_SHIFT => “Shift”). It also has a few exceptional cases, like VK_META => “Command” (Mac) or “Windows Key” (other platforms), and control characters less than 32 (e.g. Control + D) will return the expected key (e.g. “D”).

Just another Mac note… If a user holds Alt (aka “Option”) and enters a letter key, it will show up as a symbol like ‘ƒ’ instead of F or ‘√’ instead of V. If you want the returned text to be the key itself (rather than the inserted symbol), use the text from the VK_ field (code) rather than the result of keyEvent.getKeyChar.

A few comments. First, why not call put the result of fixName into the map? Second, you assume that if you’re not using a Mac then you’re using a Windows computer. Finally, you override the default key text look up no matter what. This will cause problems if the user speaks a different language, uses a different type of keyboard, does not understand what key the Java constant name refers to, or if platform’s key naming conventions change.

Instead, all you really need to replace are those single glyph names. Someone might fix that problem on Apple’s Java platform in the near future so that getKeyText actually returns text. That way you can work around the problem and only the problematic part without maintaining separate properties files or diverging from the expected key naming conventions.

That’s true for all platforms.

Ultimately it has to do with keyboard manufacturer. An Apple computer uses the terms “Command” and “Option”. Microsoft, Logitech, HP, etc. keyboards use the “Windows Key” and “Alt” buttons (even if it’s on a Linux OS). Linux users call it the “Windows Key” unless I’m mistaken…

[quote]Finally, you override the default key text look up no matter what. This will cause problems if the user speaks a different language, uses a different type of keyboard, does not understand what key the Java constant name refers to, or if platform’s key naming conventions change.
[/quote]
Hence my comment in code: “this should really be localized in a properties file!”

Yes, it would probably be best to use the AWT localizations as much as possible. My code was just a brief example of an alternative; instead of trying to nitpick it line by line, why don’t you write up your own solution and post it? ::slight_smile:

Uhh… Nope.