In the last entry, I wrote a very basic menu-driven Java program, which allows the user to change the background of the Frame. In this entry, I'll go over how to add keyboard shortcuts to this app.
We'll just have ShortcutFrame implement KeyListener and add a keyPressed(KeyEvent) method.
Our class declaration is now as follows:
public class ShortcutFrame extends Frame
implements KeyListener
in the first line of the constructor we add
addKeyListener(this);
Then we need to implement the three methods for KeyListener.
To get started, I'll use the Source -> Implement Methods feature of Eclipse, which is really useful in these cases. This takes care of a lot of busy work.
I'll leave keyTyped() and keyReleased() methods empty. I'll only flesh-out the keyPressed method.
public void keyPressed (KeyEvent event)
{
char eventChar = event.getKeyChar();
int eventCode = event.getKeyCode();
if (eventChar == 'r')
{
performCommandRed();
}
else if (eventChar == 'b')
{
performCommandBlue();
}
else if (eventCode == KeyEvent.VK_PAGE_DOWN)
{
performCommandSwitch();
}
}
Now imagine that a new customer wants this exact same program. But, they want the keyboard shortcuts to be as follows:
Hit the '1' key for Red
Hit the '2' key for Blue
Hit ctrl PAGE_DOWN to cycle.
You need to keep the one code base, but you need multiple keystroke sets.
I had to solve this same problem. The first thing I thought of was, how to come up with a language to define key strokes. Something like this:
param name="redKey" value="R"
param name="blueKey" value="1"
param name="switchKey" value="CTRL-PAGE_DOWN"
I thought about the best way to define most of the key combinations. Then I figured someone must have already solved this problem, so I did some searching and got a hit on the Javadoc page for javax.swing.KeyStroke. The method that interested me most was getKeyStroke(String s)
There is a language to define keystrokes:
getKeyStroke (String s):
Parses a string and returns a KeyStroke. The string must have the following syntax:
<modifiers>* (<typedID> | <pressedReleasedID>)
modifiers := shift | control | ctrl | meta | alt | button1 | button2 | button3
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_".
If typed, pressed or released is not specified, pressed is assumed. Here are some examples:
"INSERT" => getKeyStroke(KeyEvent.VK_INSERT, 0);
"control DELETE" => getKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
"alt shift X" => getKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
"alt shift released X" => getKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
"typed a" => getKeyStroke('a');
So now I'll define three static constants for my three key strokes;
private static KeyStroke gKeystrokeRed = KeyStroke.getKeyStroke("pressed R");
private static KeyStroke gKeystrokeBlue = KeyStroke.getKeyStroke("pressed B");
private static KeyStroke gKeystrokeSwitch = KeyStroke.getKeyStroke("PAGE_DOWN");
my keyPressed method looks like this:
public void keyPressed(KeyEvent event)
{
KeyStroke myKeyStroke = KeyStroke.getKeyStrokeForEvent(event);
if (myKeyStroke.equals(gKeystrokeRed))
{
performCommandRed();
}
else if (myKeyStroke.equals(gKeystrokeBlue))
{
performCommandBlue();
}
else if (myKeyStroke.equals(gKeystrokeSwitch))
{
performCommandSwitch();
}
}
Now if I want to change any of these, I can read in an Applet parameter.
...
getKeyStrokeParameter(applet, "keyStrokeRed", gKeystrokeRed);
getKeyStrokeParameter(applet, "keyStrokeBlue", gKeystrokeBlue);
getKeyStrokeParameter(applet, "keyStrokeSwitch", gKeystrokeSwitch);
...
public static void getKeyStrokeParameter(Applet applet,
String param,
KeyStroke shortcut)
{
String paramValue = applet.getParameter(param);
if (paramValue != null)
{
shortcut = KeyStroke.getKeyStroke(paramValue);
}
}
Now anyone can override the keyboard shortcuts with whatever they like, via applet parameters.
-Alex
Comments