2

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.

Be Brave Be Like Ukraine
  • 7,596
  • 3
  • 42
  • 66
Jemp
  • 351
  • 3
  • 7
  • 18

4 Answers4

1

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"));
kleopatra
  • 51,061
  • 28
  • 99
  • 211
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

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I use swing in my application. Can you provide me some codes? Thank you for your reply. – Jemp Dec 11 '11 at 15:02
  • code examples are 1) in the tutorial, 2) on this forum, 3) http://www.java2s.com/Tutorial/Java/CatalogJava.htm, for reall help you have edit yout post with http://sscce.org/ – mKorbel Dec 11 '11 at 15:14
  • are you some problem or bad experiences (excluding KeyListener) from some of them, simple just don't believe – mKorbel Dec 11 '11 at 17:10
0

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);

}

Anonymous
  • 152
  • 1
  • 1
  • 11
0

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();


} 
Artog
  • 1,132
  • 1
  • 13
  • 25