How can I detect CTRL+SHIFT+ANY_KEY using a KeyAdapter?

1.9k Views Asked by At

Here's my code:

        tabbedPane.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {

                CheckShortcut controlShortcut = (key) -> {
                    return (evt.getKeyCode() == key) && ((evt.getModifiers() & KeyEvent.CTRL_MASK) != 0);
                };

                CheckShortcut controlShiftShortcut = (key) -> {
                    return (evt.getKeyCode() == key) && ((evt.getModifiers() & KeyEvent.CTRL_MASK & KeyEvent.SHIFT_MASK) != 0);
                }; // Does not work <<<<<

                if (controlShortcut.f(KeyEvent.VK_N)) {
                    createNewFile();
                } else if (controlShortcut.f(KeyEvent.VK_O)) {
                    openFile();
                } else if (controlShortcut.f(KeyEvent.VK_S)) {
                    save();
                } else if (controlShiftShortcut.f(KeyEvent.VK_S)) {
                    saveAs();
                } else if (controlShortcut.f(KeyEvent.VK_Q)) {
                    System.exit(0);
                } else if (controlShortcut.f(KeyEvent.VK_W)) {
                    MainFrame.toggleFrame(qrWebcamFrame);
                } else if (controlShortcut.f(KeyEvent.VK_C)) {
                    MainFrame.toggleFrame(comandaCreationFrame);
                } else if (controlShortcut.f(KeyEvent.VK_P)) {
                    if (accessPasswordFrame("Senha de administrador",
                            "Login: ", "Senha de administrador inválida.",
                            ADMIN_TYPE)) {
                        MainFrame.toggleFrame(passwordFrame);
                    }
                }

            }   
        });

The controlShortcut works perfectly. Nevertheless, when I add KeyEvent.SHIFT_MASK to the test, it does not work. Also, when I do this:

        CheckShortcut controlShiftShortcut = (key) -> {
            return (evt.getKeyCode() == key) && ((evt.getModifiers() & KeyEvent.CTRL_MASK) != 0) && ((evt.getModifiers() & KeyEvent.SHIFT_MASK) != 0);
        };

It does not work as well. I don't understand why, since I'm just adding the same test.

3

There are 3 best solutions below

4
user1803551 On BEST ANSWER

This is not how bitwise operators work. KeyEvent.CTRL_MASK & KeyEvent.SHIFT_MASK always gives 0 because you are AND-ing different masks.

What you want to do is create a mask for both using OR:

int down = KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK;
if ((e.getModifiersEx() & down) == down && (e.getKeyCode() == KeyEvent.VK_D))
    System.out.println(true);

This will print

true

only when ctrl+shift+D is pressed.

If you write

(e.getModifiersEx() & down) != 0

it will check if any (or both) of ctrl or shift are pressed.

Note that you should use getModifiersEx along with X_DOWN_MASK and not getModifiers along with X_MASK.

6
stelar7 On

You are using the wrong bitwise-operator on the masks.
See the JavaDocs

The correct way should be:

int mask = CTRL_DOWN_MASK | SHIFT_DOWN_MASK;
if(evt.getModifiersEx() & mask == mask) {doStuff();}  

See also the following methods:

evt.isControlDown();
evt.isAltDown();
evt.isShiftDown();
0
kreinerjm On

You could just create two boolean values for shift and control.

public class DummyClass implements KeyListener{
    boolean shift = false, control = false;

    public void KeyPressed(KeyEvent e)
    {
        if(e.getKeyCode() == KeyEvent.VK_SHIFT)
        {
            shift = true;
        }        
        if(e.getKeyCode() == KeyEvent.VK_CONTROL)
        {
            control = true;
        }
        if(shift && control)
        { 
            //Do something 
        }
        else if(shift)
        { 
            //Do something
        }
        else if(control)
        { 
            //Do something 
        }
    }
    public void KeyReleased(KeyEvent e)
    {
        if(e.getKeyCode() == KeyEvent.VK_SHIFT)
        {
            shift = false;
        }        
        if(e.getKeyCode() == KeyEvent.VK_CONTROL)
        {
            control = false;
        }
    }
}