KeyStroke в InputMap только для CTRL должен иметь CTRL_DOWN_MASK и CTRL_MASK (только для win10)

У меня есть пользовательский компонент (унаследованный от JComponent), и мне нравится подчеркивать ссылку, удерживая нажатой CTRL вправо, как это делает eclipse. Я решил использовать InputMap и ActionMap для функции нажатия/отпускания клавиши.

Я использую этот код, чтобы найти ход:

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

Но это как-то неправильно. Я отладил метод processKeyBinding JComponent и обнаружил, что если я нажму CTRL, появится KeyStroke с модификатором 130.

введите здесь описание изображения

(это — моя карта ввода, arg0 — входящее нажатие клавиши с клавиатуры)

Я думаю, что 130 — это результат сложения CTRL_DOWN_MASK с кодом 128 и CTRL_MASK с кодом 2.

  1. Почему я должен добавить эти модификаторы?
  2. Это кроссплатформенный?
  3. Есть ли официальная документация?

Полный пример запросов camickr:

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

person Grim    schedule 02.04.2016    source источник
comment
Как указано в JavaDocs - Константа-модификатор клавиши Control. Вместо этого рекомендуется использовать CTRL_DOWN_MASK. - Причина может заключаться в том, что какая-то часть API была изменена, вероятно, для устранения ошибки, и переключился на использование CTRL_MASK_DOWN в целом.   -  person MadProgrammer    schedule 02.04.2016
comment
Вы имеете в виду, что хотите выделить ссылку с помощью мыши, когда клавиша управления нажата? Для этого вы можете проверить свойства MouseEvent   -  person MadProgrammer    schedule 02.04.2016
comment
@MadProgammer 1. InputMap не работает таким образом, InputMap использует метод равенства AWTKeyStroke. 2. Нет, давайте предположим, что я навел указатель мыши на ссылку, и без перемещения мыши я нажимаю CTRL, нажатие клавиши на клавиатуре не является перемещением мыши, и никакие MouseEvent не сработают.   -  person Grim    schedule 02.04.2016
comment
Извините, что (вы имеете в виду под своим первым пунктом?!). Я думаю, если вы посмотрите на KeyStroke#getKeyStroke вы увидите, что можете передать ему модификатор, в документах говорится, что x_DOWN_MASK предпочтительнее старого x_MASK   -  person MadProgrammer    schedule 02.04.2016
comment
Что касается вашего второго пункта, я все еще думаю, что MouseMotionListener является предпочтительным решением, поскольку MouseEvent предоставляет параметр modifier, сообщающий вам, какие клавиши нажаты (shift/alt/ctrl), но это я   -  person MadProgrammer    schedule 02.04.2016
comment
@MadProgrammer Ко второму пункту: как я уже говорил вам ранее, событие клавиатуры — это не событие мыши!   -  person Grim    schedule 02.04.2016
comment
Да, я прекрасно об этом знаю, все, что я говорю, это то, что MouseEvent имеет хороший isControlDown (и другие) mwthos, которые подойдут. Имейте в виду, я никогда не мог заставить VK_CONTROL работать в качестве привязки клавиш, так что это может объяснить, почему я предпочитаю использовать MouseMoitionListener, но если это не то, что вам нужно, это ваш выбор, и мы можем просто оставить его. при этом.   -  person MadProgrammer    schedule 02.04.2016
comment
@MadProgrammer Да, слушать только на VK_CONTROL с помощью какого-то KeyListener невозможно, нужно использовать InputMap и ActionMap, потому что CTRL — это какая-то специальная клавиша.   -  person Grim    schedule 02.04.2016
comment
Я попробовал решение camickr, и оно у меня работает.   -  person MadProgrammer    schedule 02.04.2016
comment
Очень интересно, похоже, это не кроссплатформенная совместимость и, возможно, ошибка. Какую ОС вы используете?   -  person Grim    schedule 02.04.2016
comment
Я использовал MacOS 10.11.4 и Java 8.   -  person MadProgrammer    schedule 02.04.2016
comment
У вас тоже работает KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_MASK + KeyEvent.CTRL_DOWN_MASK);?   -  person Grim    schedule 02.04.2016
comment
Нет, модификаторы должны быть |, например , но проверим их или вместе   -  person MadProgrammer    schedule 02.04.2016
comment
KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_DOWN_MASK | KeyEvent.CTRL_MASK) и KeyStroke.getKeyStroke(KeyEvent.VK_CONTROL, KeyEvent.CTRL_MASK) вроде работают   -  person MadProgrammer    schedule 02.04.2016
comment
Без CTRL_DOWN_MASK win10 не работает. Я сообщу об ошибке. Пока ошибка не исправлена, я использую KeyEvent.CTRL_DOWN_MASK | KeyEvent.CTRL_MASK, потому что она работает на Win10 и Mac. Часто ли шрифт увеличивается в полном коде (SSCCE), который я разместил в вопросе?   -  person Grim    schedule 02.04.2016
comment
Шрифт растет на чем? Это может быть особенность Windows 10   -  person MadProgrammer    schedule 02.04.2016


Ответы (1)


1. Зачем мне добавлять эти модификаторы?

Вам не нужно добавлять оба модификатора, только CTRL_DOWN_MASK.

Итак, для создания KeyStroke вы можете использовать:

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

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

Я не знаю какой-либо документации, в которой прямо говорится, что вам нужно это сделать, но «клавиши-модификаторы» отличаются от других клавиш на клавиатуре.

person camickr    schedule 02.04.2016
comment
Нет, они не могут работать без модификатора 130! См. AWTKeyStroke#equals, его вызывает InputMap.get(). - person Grim; 02.04.2016
comment
Я не работаю с магическими числами. 130 для меня ничего не значит. Вышеуказанные KeyStrokes работают для меня. Это действие, которое я добавляю в ActionMap, вызывается, когда я нажимаю клавишу CTRL. Опубликуйте свой SSCCE, демонстрирующий проблему, если он не работает для вас. - person camickr; 02.04.2016
comment
Никогда бы не подумал объединить VK_CONTROL с CTRL_DOWN_MASK, мило - person MadProgrammer; 02.04.2016
comment
См. редактирование выше, и если вы все еще говорите мне, что можете удалить KeyEvent.CTRL_MASK, пожалуйста, опубликуйте свою os/jdk, моя - win10/1.8.0_31. - person Grim; 02.04.2016
comment
Кстати: использование элемента управления CONTROL и удерживание Ctrl позволяет часто увеличивать шрифт, это не то, что я хочу. - person Grim; 02.04.2016
comment
@PeterRader, что за минус? все, что я сказал в ответе, верно. you can drop the KeyEvent.CTRL_MASK - да, могу. Я использую JDK8 в Windows 7. Вот почему SSCCE и OS/JDK следует публиковать с каждым вопросом, чтобы люди могли проверить, есть ли у них те же проблемы. holding Ctrl let frequently grows the font, - Это нормальное поведение. удерживание любой клавиши будет генерировать несколько событий mousePressed. Оба KeyStrokes работают таким образом для меня. - person camickr; 02.04.2016
comment
@MadProgrammer, иногда я не знаю, о чем думает мой разум, но мне везет :) - person camickr; 02.04.2016
comment
@camickr Причина в вашем комментарии не имеет смысла, но вы расстроены, и я удаляю отрицательный голос. Блин, я не могу убрать минус, пока кто-нибудь не отредактирует. - person Grim; 03.04.2016
comment
@PeterRader, тот факт, что это не работает для вас, не делает ответ неверным, потому что он действительно работает для меня. На самом деле вы должны принять ответ, потому что мое настояние на том, чтобы вы опубликовали свой SSCCE, в конечном итоге приведет к выводу, что ваша проблема связана с платформой, поэтому на вопрос был дан ответ. - person camickr; 03.04.2016
comment
@camickr С моей точки зрения: первый ответ неверен. На второй вопрос отвечают комментарии. А не знаю по 3му вопросу низкое качество. Я хотел бы удалить отрицательный голос, потому что вы расстроены, но теперь вы хотите, чтобы я принял ответ, что, на мой взгляд, неправильно и имеет низкое качество? - person Grim; 03.04.2016
comment
@PeterRader Это НЕ неправильно. Одна строка кода, которую вы включили, НЕ работала для меня, поэтому я дал простой ответ, что ДЕЙСТВИТЕЛЬНО работал для меня (и это было подтверждено MadProgrammer). То, что вы постоянно заявляете, что это неправильно, когда два человека подтверждают, что это работает, ошеломляет. Кроме того, вы затем голосуете против ответа, потому что он вам не подходит ??? Как это побуждает людей тратить время на решение ваших проблем? Без моих замечаний и предложений ваш вопрос не был бы решен. - person camickr; 03.04.2016
comment
Извините, я не понимаю. Какую строку кода вы имеете в виду? KeyStroke.getKeyStroke("pressed CONTROL");? - person Grim; 04.04.2016
comment
@PeterRader, именно в вашем исходном вопросе это все, что вы разместили. Это НЕ сработало для меня, поэтому я исправил эту единственную строку кода двумя предложениями, которые сработали для меня (и для MadProgrammer), предполагая, что это также сработает для вас, и вам не нужно будет использовать две маски. Как оказалось, вам нужны две маски из-за ошибки Windows. Но вы, конечно, не можете винить меня за мою попытку, основанную на информации, которую вы представили в своем первоначальном вопросе. - person camickr; 04.04.2016