javaswingkeylistenerkeyeventkey-events

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


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.


Solution

  • 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.