2

I have a custom component (inherited from JComponent) and like to underline a link while holding CTRL pressed right like eclipse does. I decide to use InputMap and ActionMap for keypress/release feature.

I use this code to find the stroke:

stroke = KeyStroke.getKeyStroke("pressed CONTROL");

But it is wrong somehow. I debugged the processKeyBinding method of JComponent and find out that if i press CTRL a KeyStroke having modifier 130.

enter image description here

(this is my InputMap, arg0 is the incomming KeyStroke from the Keyboard)

I think 130 is the result of the addition of CTRL_DOWN_MASK who has code 128 and CTRL_MASK has code 2.

  1. Why do i have to add theese modifiers?
  2. Is this cross-platform?
  3. Is there any official documentation?

Full example camickr requests:

public class Test extends JLabel {
    public static void main(String[] args) {
        final JFrame jf = new JFrame("Test");
        final Test label = new Test();
        jf.getContentPane().add(label);
        jf.setBounds(200, 200, 500, 500);
        jf.pack();
        jf.setVisible(true);
        label.grabFocus();
    }

    public Test() {
        super("Foobar");
        addBoldOnCtrl();
    }

    public void addBoldOnCtrl() {
        final KeyStroke onDown = KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_MASK + KeyEvent.CTRL_DOWN_MASK);
        final String onDownName = "react on ctrl";
        getInputMap().put(onDown, onDownName);
        getActionMap().put(onDownName, new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                final Font f = getFont();
                setFont(new Font(f.getFontName(), f.getStyle(), f.getSize() + 2));
                repaint();
            }
        });
    }
}
Grim
  • 1,938
  • 10
  • 56
  • 123
  • As stated in the [JavaDocs](https://docs.oracle.com/javase/7/docs/api/java/awt/event/InputEvent.html#CTRL_MASK) - *"The Control key modifier constant. It is recommended that CTRL_DOWN_MASK be used instead. "* - The reasoning would be that some part of the API was changed, probably to overcome a bug, and switched to preferring to use `CTRL_MASK_DOWN` generally – MadProgrammer Apr 02 '16 at 04:46
  • Do you mean you want to highlight a link using the mouse when the control key is down? For that you can inspect the properties of the `MouseEvent` – MadProgrammer Apr 02 '16 at 04:47
  • @MadProgammer 1. InputMap does not work this way, InputMap uses the equals-method of the `AWTKeyStroke`. 2. No, lets assume i move the mouse over the link and without a mousemove i press CTRL the press of the key on the keyboard is not a mouse-move and no `MouseEvent` will be triggered. – Grim Apr 02 '16 at 04:50
  • I'm sorry, what (do you mean by your first point?!). I think if you take a look at [`KeyStroke#getKeyStroke`](https://docs.oracle.com/javase/8/docs/api/javax/swing/KeyStroke.html#getKeyStroke-int-int-) you will see that you can pass a modifier to it, the docs say that `x_DOWN_MASK` is preferred over the older `x_MASK` – MadProgrammer Apr 02 '16 at 05:12
  • As to your second point, I still think a `MouseMotionListener` is a preferred solution, as the `MouseEvent` provides a `modifier` parameter telling you which keys are down (shift/alt/ctrl), but that's me – MadProgrammer Apr 02 '16 at 05:14
  • @MadProgrammer To the second point: As i told you before, a keyboard-event is not a mouse-event! – Grim Apr 02 '16 at 05:40
  • Yes, I'm well aware of that, all I'm saying is the `MouseEvent` has a nice [`isControlDown`](https://docs.oracle.com/javase/7/docs/api/java/awt/event/InputEvent.html#isControlDown()) (and others) mwthos which would suit. Mind you, I've never been able to get `VK_CONTROL` to work as a key binding, so that might explain why I'd prefer to use a `MouseMoitionListener`, but if that's not what you want, that's your choice and we can just leave it at that. – MadProgrammer Apr 02 '16 at 05:44
  • @MadProgrammer Yes, to listen only on the VK_CONTROL using some kind of KeyListener is not possible, you need to use `InputMap` and `ActionMap` because CTRL is some kind of a special key. – Grim Apr 02 '16 at 06:06
  • I tried camickr's solution and it works for me – MadProgrammer Apr 02 '16 at 06:07
  • Very interresting, looks like it is not cross-platform compatible and maybe a bug. What OS do you use? – Grim Apr 02 '16 at 06:08
  • 1
    I was using MacOS 10.11.4 and Java 8 – MadProgrammer Apr 02 '16 at 06:09
  • Does `KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_MASK + KeyEvent.CTRL_DOWN_MASK);` works for you too? – Grim Apr 02 '16 at 06:11
  • No, it won't, the modifers need to be `|`, for [example](http://stackoverflow.com/questions/15605109/java-keybinding-plus-key/15605266#15605266), but will test them or'd together – MadProgrammer Apr 02 '16 at 06:16
  • `KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_DOWN_MASK | KeyEvent.CTRL_MASK)` and `KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_MASK)` both seem to work – MadProgrammer Apr 02 '16 at 06:18
  • Without `CTRL_DOWN_MASK` win10 does not work. I will report a bug. As long as the bug is not fixed i use `KeyEvent.CTRL_DOWN_MASK | KeyEvent.CTRL_MASK` because it works on win10 and mac. Does the font grow frequently on the complete code (SSCCE) i posted in the question? – Grim Apr 02 '16 at 06:21
  • Font grow on what? That could be Windows 10 "feature" – MadProgrammer Apr 02 '16 at 06:22

1 Answers1

1

1.Why do i have to add theese modifiers?

You don't have to add both modifiers, just the CTRL_DOWN_MASK.

So to create the KeyStroke you can use:

KeyStroke ks = KeyStroke.getKeyStroke("control CONTROL");

KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_DOWN_MASK);

I don't know of any documentation that explicitly states you need to do this but the "modifier keys" are different than other keys on the keyboard.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • No, they can not work without modifier `130`! See `AWTKeyStroke#equals`, its called by `InputMap.get()`. – Grim Apr 02 '16 at 05:38
  • 1
    I don't work with magic numbers. 130 means nothing to me. The above KeyStrokes work for me. That is the Action I add to the ActionMap is invoked when I press the CTRL key. Post your [SSCCE](http://sscce.org/) demonstrating the problem if it doesn't work for you. – camickr Apr 02 '16 at 05:48
  • I would never have thought to combine `VK_CONTROL` with `CTRL_DOWN_MASK`, nice – MadProgrammer Apr 02 '16 at 05:51
  • See the edit above and if you still teling me you can drop the `KeyEvent.CTRL_MASK` please post your os/jdk, mine is win10/1.8.0_31. – Grim Apr 02 '16 at 05:58
  • BTW: Using "control CONTROL" and holding Ctrl let frequently grows the font, this is not what i want. – Grim Apr 02 '16 at 06:17
  • @PeterRader, Whats with the downvote? everything I stated in the answer is accurate. `you can drop the KeyEvent.CTRL_MASK` - yes I can. I'm using JDK8 on Windows 7. This is why a `SSCCE` and OS/ JDK should be posted with every question so people can test to see if they have the same problems. `holding Ctrl let frequently grows the font,` - This is normal behaviour. holding down any key will generate multiple mousePressed events. Both KeyStrokes work this way for me. – camickr Apr 02 '16 at 15:25
  • 1
    @MadProgrammer, sometimes I don't know what my mind is thinking but I get lucky :) – camickr Apr 02 '16 at 15:29
  • @camickr The reason in your comment does not make sense, but you are upset and i remove the downvote. Dam, i can not remove the downvote until someone edit it. – Grim Apr 03 '16 at 07:16
  • @PeterRader, that fact that is doesn't work for you does not make the answer incorrect because it does in fact work for me. In fact you should actually be "accepting" the answer because my insistence for you to post your SSCCE ultimately lead to the conclusion that your problem is platform related so the question has been answered. – camickr Apr 03 '16 at 18:47
  • @camickr From my point of view: the first answer is wrong. The second question is answered by the comments. A "I do not know" for the 3rd question is low quality. Id like to remove the downvote because you are upset, but now you like me to accept a answer what in my eyes is wrong and has low quality? – Grim Apr 03 '16 at 19:06
  • @PeterRader It is NOT wrong. The single line of code you included did NOT work for me so I gave a simple answer that DID work for me (and it was confirmed by MadProgrammer). For you to continually state it was wrong when two people confirm it works is mindboggling. In addition you then down vote the answer because it doesn't work for you??? How does that encourage people to take the time to try and resolve your problems? Without my comments and suggestions your question would not be resolved. – camickr Apr 03 '16 at 20:40
  • Sorry, i did not get it. What single line of code do you mean? `KeyStroke.getKeyStroke("pressed CONTROL");`? – Grim Apr 03 '16 at 21:34
  • @PeterRader, Exactly in your original question that is all you posted. That did NOT work for me, so I corrected that single line of code with two suggestions that did work for me (and for MadProgrammer) assuming it would also work for you and you would not need to use the two masks. As it turns out you need the two masks because of a Windows bug. But you sure can't blame me for my attempt based on the information you presented in your original question. – camickr Apr 03 '16 at 23:19