Как определить комбинацию клавиш модификатора при нажатии кнопки в java

У меня есть кнопка в приложении Java Swing для увеличения выделения. Я реализовал 3 способа нажатия на него:

  • щелчок: увеличивает выделение с пошаговой анимацией
  • option-click: делает один шаг масштабирования к выделению
  • Command-щелчок: внезапное увеличение до полного выбора

Я хотел бы реализовать обратное поведение (т.е. масштабировать от выделение наружу до полного уменьшения), когда дополнительно удерживается клавиша Shift, так что это будет так:

  • Shift-щелчок: полное уменьшение масштаба с пошаговой анимацией
  • Shift-option-щелчок: делает один шаг масштабирования от выделения
  • Shift-Command-щелчок: внезапное увеличение до полного уменьшения

Я знаю, как делать все, кроме Shift-Option-Click и Shift-Command-Click. Например. Вот как я делаю одношаговое увеличение:

int stepMask = InputEvent.ALT_MASK;
if((e.getModifiers() & InputEvent.ALT_MASK) == stepMask) {
    //do the single-step zoom
}

Но я не могу понять, как сделать комбинацию клавиш одним щелчком мыши. Все, что я пробовал, работает только с одной клавишей-модификатором. Как определить комбинацию клавиш при нажатии кнопки?


person hepcat72    schedule 10.04.2015    source источник


Ответы (2)


Значение modifiers представляет собой значение побитового ИЛИ, содержащее все модификаторы InputEvent, связанные с событием. Чтобы определить конкретные модификаторы, отметьте все, что вы считаете необходимым для данной логики:

if((e.getModifiers() & InputEvent.ALT_MASK) != 0 && (e.getModifiers() & InputEvent.SHIFT_MASK) != 0 ) {
    //code for event
}
person copeg    schedule 10.04.2015
comment
Почему бы не упростить это до if((e.getModifiers() & (InputEvent.ALT_MASK | InputEvent.SHIFT_MASK) != 0 ) { // код для события } - person Gordon; 28.08.2015
comment
@Gordon, потому что этот код будет выполняться, если будет удерживаться клавиша Alt или shift. - person JakeRobb; 06.04.2017
comment
Нет, не будет. Это маска. - person Gordon; 06.04.2017

Есть более изящный подход. Во-первых, определите вашу комбинированную маску как константу:

private static final int SHIFT_OPTION_MASK = InputEvent.ALT_MASK | InputEvent.SHIFT_MASK;

Затем в ActionListener кнопки сделайте следующее:

if((e.getModifiers() & SHIFT_OPTION_MASK) == SHIFT_OPTION_MASK) {
    // code for event
}

Если у вас их много, вы можете пойти еще дальше. Начните с определения перечисления:

import java.awt.event.InputEvent;

public enum ModifierKey {
    ALT(InputEvent.ALT_MASK),
    SHIFT(InputEvent.SHIFT_MASK),
    CONTROL(InputEvent.CTRL_MASK),
    COMMAND(InputEvent.META_MASK);
    // add more enum values here as needed

    public static boolean checkFor(ActionEvent e, ModifierKey... expectedModifiers) {
        int expectedModifierMask = 0;
        for (ModifierKey expectedModifier : expectedModifiers) {
            expectedModifierMask |= expectedModifier.getMask();
        }
        return (e.getModifiers() & expectedModifierMask) == expectedModifierMask;
    }

    private final int mask;

    ModifierKey(int mask) {
        this.mask = mask;
    }

    public int getMask() {
        return mask;
    }
}

Затем в вашем actionListener вы можете сделать это вместо этого:

import static ModifierKey.*;

...

if (checkFor(e, OPTION, SHIFT)) {
    // code for event
}
person JakeRobb    schedule 06.04.2017
comment
Анонимному даунвотеру, не могли бы вы прокомментировать? Я использую это на практике. Он работает отлично, и ИМО намного читабельнее. - person JakeRobb; 12.05.2017
comment
20+ строк и код, который использует пользовательский метод в каждом случае, который кто-то другой, касающийся кода, должен помнить, чтобы использовать или искать, когда они впервые видят его, по сравнению с одной строкой if((e.getModifiers() & (InputEvent.ALT_MASK | InputEvent.SHIFT_MASK) != 0 ), которая сама по себе прекрасно читается? Это не похоже на то, что константы InputEvent имеют запутанные названия. Как ваша версия намного читабельнее? Для меня это выглядит как шаблон ради шаблона. - person Gordon; 20.05.2017
comment
Вы более чем приветствуете это мнение. :) В моем относительно большом приложении Swing я использую функцию checkFor в десятках мест (обратите внимание, что в моем ответе я написал, если у вас их много. Я считаю, что каждое из них более читабельно и легче получить правильный синтаксис, поэтому дополнительные двадцать строк (которые мне никогда не приходится трогать) легко окупаются. - person JakeRobb; 20.05.2017
comment
Кроме того, каждый вызов checkFor на несколько символов короче, чем эквивалентный необработанный подход, не говоря уже о том, что он не включает никаких побитовых манипуляций, которые я считаю подверженными ошибкам. Потратив десять минут на написание этих двадцати строк, я экономлю тридцать секунд каждый раз, когда мне нужно проверить ключи-модификаторы. - person JakeRobb; 20.05.2017