问题
I'm doing a project that needs to detect if a certain key combination has been pressed. Any keys like Ctrl, Alt, A-Z and 0-9 can be used as key combination.
I've searched some codes using KeyStroke.getKeyStroke
but it seems like it does not allow combinations without a Ctrl, Shift, Alt, etc.
My application needs to detect combinations even WITHOUT Ctrl or Alt e.g. just a combination of plain A+B+C. Is this can also be done withKeyStroke.getKeyStroke
? Replies are greatly appreciated.
回答1:
Depends of if applications type if has GUI or not, for GUI rellated you have to look for
DocumentListener and KeyBindings, and I suggest to refuse implements KeyListener for more than complicated code and Focus workaround
or add addAWTEventListener(AWTEventListener listener, long eventMask) and there is possible listening for KeyEvents and MouseEvents too
回答2:
AFAIK, there is no way to get the status of a key, that is nothing like:
KeyStroke keyStroke = KeyStroke.getKeyStroke("A");
// NOT supported
if (keyStroke.isPressed()) {
// do something
}
The only thingy supported is notification about change of a single key's status, f.i. at the lowest level in a KeyListener
public void keyPressed(KeyEvent e) {
if (KeyEvent.VK_A == e.getKeyCode()) {
....
}
}
To handle key combinations (except with special modifier keys), there is no way around keeping track of which keys have been pressed/released to know which are in a pressed state.
Below is an example of doing so on the level of keyBindings. The basic ingredients
- Trigger: the entity containing the logic of accumulative "arming" of the ultimate action to perform
- an Action which dis/arms the trigger
- keyBindings for both released/pressed of particual key strokes, bound to the corresponding arming action
Some code:
// the logic container
public static interface Trigger {
public void addTrigger(String trigger);
public void arm(ActionEvent e);
public void disarm(ActionEvent e);
}
// a particular implementation which uses the actionCommand
// as identifiers
public static class ActionTrigger implements Trigger {
private Action triggered;
private List<String> triggers = new ArrayList<>();
private List<String> armed = new ArrayList<>();
public ActionTrigger(Action triggered) {
this.triggered = triggered;
}
@Override
public void arm(ActionEvent e) {
String command = e.getActionCommand();
if (!triggers.remove(command)) return;
armed.add(command);
if (triggers.isEmpty()) {
triggered.actionPerformed(e);
}
}
@Override
public void disarm(ActionEvent e) {
String command = e.getActionCommand();
if (!armed.remove(command)) return;
triggers.add(command);
}
@Override
public void addTrigger(String trigger) {
triggers.add(trigger);
}
}
// an Action notifying the trigger of dis/arms
public static class ArmingAction extends AbstractAction {
private Trigger trigger;
private boolean arm;
/**
* @param trigger
*/
public ArmingAction(Trigger trigger, String command, boolean arm) {
this.trigger = trigger;
this.arm = arm;
putValue(ACTION_COMMAND_KEY, command);
}
@Override
public void actionPerformed(ActionEvent e) {
if (arm) {
trigger.arm(e);
} else {
trigger.disarm(e);
}
}
}
// usage
// the action to trigger with multiple keys
Action action = new AbstractAction("real") {
@Override
public void actionPerformed(ActionEvent e) {
LOG.info("******triggered: " + e);
}
};
JComponent comp = new JPanel();
ActionMap actionMap = comp.getActionMap();
InputMap inputMap = comp.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
Trigger trigger = new ActionTrigger(action);
// the key combination
char[] chars = {'A', 'S', 'D'};
for (int i = 0; i < chars.length; i++) {
// the identifier
String command = "step" + chars[i];
trigger.addTrigger(command);
// binding for pressed
String pressedID = "pressed" + chars[i];
actionMap.put(pressedID, new ArmingAction(trigger, command, true));
inputMap.put(KeyStroke.getKeyStroke("pressed " + chars[i]), pressedID);
// binding for released
String releasedID = "released" + chars[i];
actionMap.put(releasedID, new ArmingAction(trigger, command, false));
inputMap.put(KeyStroke.getKeyStroke("released " + chars[i]), releasedID);
}
comp.add(new JButton("multibindings ... a s d"));
回答3:
You can play keyPressed and keyReleased method of KeyListener. If u type with ur keyboard, keyPressed event first occour before keyReleased. You can get key event in key pressed and catch that combination key in key released with business logic.
public void keyPressed(KeyEvent evt) {
keyHit = KeyEvent.getKeyText(evt.getKeyCode());
System.out.println("Key Pressed is "+keyHit);
}
public void keyReleased(KeyEvent evt) {
stringBuffer.append(keyHit)
System.out.println("Key Released is "+keyHit);
}
回答4:
I tried many methods and finally found out a method which can be excuted by any two key combination.
Below is my GUI project code:
Boolean k4 = false;
Boolean k5 = false;
Boolean k6 = false;
Boolean ke = false;
Boolean vs = false;
private void jLabel1KeyPressed(java.awt.event.KeyEvent evt) {
int i = evt.getKeyCode();
switch(i) {
case VK_NUMPAD4 : k4=true; break;
case VK_NUMPAD5 : k5= true; break;
case VK_NUMPAD6 : k6 = true; break;
case VK_ENTER : ke = true; break;
case VK_SUBTRACT: vs=true; break;
}
if(k4==true && ke==true) {
jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/audit/images/banker.png")));
k4=false;
ke=false;
}
else if(k5==true && ke==true) {
jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/audit/images/tie.png")));
k5=false;
ke=false;
}
else if(k6==true && ke==true) {
jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/audit/images/player.png")));
k6=false;
ke=false;
}
else if(vs==true && ke==true) {
jLabel1.requestFocus();
jLabel1.setIcon(null);
vs=false;
ke=false;
}
enter_squence();
}
来源:https://stackoverflow.com/questions/8464727/key-combination-of-characters-non-ctrl-or-alt-in-java