9

I was trying to create shortcuts for zooming in and out in an image editing application I'm creating and I noticed something strange. To bind the combination of ctrl + +, I had to use the = key and a control and shift mask:

getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.CTRL_DOWN_MASK + KeyEvent.SHIFT_DOWN_MASK),"ZoomIn");

Neither of the combinations where I tried to directly bind to VK_PLUS worked:

getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, KeyEvent.CTRL_DOWN_MASK + KeyEvent.SHIFT_DOWN_MASK),"ZoomIn");

getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, KeyEvent.CTRL_DOWN_MASK),"ZoomIn");

It works right now with the very first line of code, but I was wondering why neither of the bottom two work and if this could (theoretically) be a problem if a keyboard did not have the + key as the shifted = key.

PeeHaa
  • 71,436
  • 58
  • 190
  • 262
scaevity
  • 3,991
  • 13
  • 39
  • 54
  • You apparently don't understand how the modifiers are used. You second example is almost right, but the second parameter is `a bitwise-ored combination of any modifiers` (from the JavaDocs) not a sum of – MadProgrammer Mar 24 '13 at 23:03
  • 1
    @MadProgrammer Yeah, I forgot that I should use bitwise-or instead of addition, but that's not the problem. – scaevity Mar 24 '13 at 23:17
  • The problem, as I see it, is you seem to be thinking that the `KeyEvent.VK_PLUS` represents the `+` symbol above the `=` symbol. I THINK that the `KeyEvent.VK_PLUS` actually represents the `+` key on the numpad instead. What you could do is use both the `KeyEvent.VK_EQUALS` with the `shift`+`ctrl` modifiers and `KeyEvent.VK_PLUS` with the `ctrl` modifier – MadProgrammer Mar 24 '13 at 23:21
  • I stand corrected, the numpad `+` is `VK_ADD` – MadProgrammer Mar 24 '13 at 23:29

3 Answers3

19

For numeric keypad plus try KeyEvent.VK_ADD:

getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ADD,
                KeyEvent.CTRL_DOWN_MASK), "plus");

For plus on main keyboard (US keyboard layout) use:

getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK),"plus"); 

For non US keyboard use VK_PLUS. See bugs 4262044 and 6942481 for some clarifications.

tenorsax
  • 21,123
  • 9
  • 60
  • 107
  • 1
    Thanks, this seems to agree with my testing! – scaevity Mar 24 '13 at 23:25
  • 1
    @scaevity you're welcome! :) There seem to be some confusion around `VK_PLUS`. Looks like it is used on the keyboards where `+` is on the primary layer, whereas on US keyboard it is on secondary layer. – tenorsax Mar 24 '13 at 23:36
  • 1
    In the same way, for `ctrl -` you have `KeyEvent.VK_MINUS` and `KeyEvent.VK_SUBTRACT` (numpad). – IvanRF May 16 '16 at 01:11
4

As I understand it, the VK_ADD is actually used for the numpad +.

In order to use the + that appears along the top of the keybaord (next to the line of numbers), you would need to phsycially type shift+=

In this case, you need to use the KeyEvent.VK_EQUALS with a KeyEvent.SHIFT_DOWN_MASK modifier.

But you also want the KeyEvent.CTRL_DOWN_MASK modifier as well.

im.put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.CTRL_DOWN_MASK | KeyEvent.SHIFT_DOWN_MASK), "Test1");

The problem you're having is that the modifiers are a bitwise-ored combination of any modifiers

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Hm... VK_ADD seems to be the numeric keyboard, but I can't get either the number pad or normal keyboard to work with VK_PLUS. – scaevity Mar 24 '13 at 23:23
  • @scaevity Yes, you are right `VK_ADD` is for the numpad. I can't find any use of the `VK_PLUS`, it might be used for different keyboard layouts. The example code I used above works fine for me... – MadProgrammer Mar 24 '13 at 23:34
  • @MadProgrammer +1, it is amazing that there is nothing about this in spec. – tenorsax Mar 24 '13 at 23:40
  • @Aqua Yeah, it's what freaked me out when testing the code :P – MadProgrammer Mar 24 '13 at 23:41
4

I ran into the same problem today: I wanted to catch Ctrl + =, which we press thinking of Ctrl + +, and associate it to a zoom in action. I use a Brazilian ABNT2 keyboard. While typing, to obtain the plus character, I need to use the combination Shift + =, so I can't catch Ctrl + + directly. I could do like @Aqua suggested, which is to actually catch Ctrl + Shift + =, but it does not seem natural to me. I decided to see how some applications solve that problem.

Notepad++ associates zoom in and zoom out to the numpad's plus and minus, respectively. That's an easy solution to the problem, but it was also not what I wanted. Mozilla Firefox, by its turn, does exactly what I want: it says that Ctrl + + is the key combination for zooming in, but what it actually catches is Ctrl + =. Additionally, it also understands if I use the numpad's plus to zoom in.

How I solved the problem

So, that's how I decided to solve the problem: while creating the Action, I associated the key combination Ctrl + + to the action of zooming in, which actually can't be caught:

Action zoomInAction = new AbstractAction() {
    @Override
    public void actionPerformed(ActionEvent event) {
        zoomIn();
    }
};

zoomInAction.putValue(AbstractAction.ACCELERATOR_KEY,
        KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, KeyEvent.CTRL_DOWN_MASK));

JMenuItem zoomInMenuItem = new JMenuItem(zoomInAction);
viewMenu.add(zoomInMenuItem);

The ace in the hole is to catch the Ctrl + = combination apart and treat it the same:

frame.addKeyListener(new KeyListener() {
    @Override
    public void keyTyped(KeyEvent event) {
    }

    @Override
    public void keyReleased(KeyEvent event) {   
    }

    @Override
    public void keyPressed(KeyEvent event) {
        if (event.isControlDown() && (event.getKeyCode() == KeyEvent.VK_EQUALS)) {
            zoomIn();
        }
    }
});

That way, the interface (i.e. the JMenuItem that corresponds to the Action) tells the user to use the key shortcut Ctrl + + to zoom in. The user then presses Ctrl + =, thinking of Ctrl + +, but the application understands that combination and acts as the user expects it to do so.

This is my first Stack Overflow answer, so sorry for anything :)

Antônio Medeiros
  • 3,068
  • 1
  • 27
  • 22