JavaFX - ускоритель не работает, когда текстовое поле имеет фокус

В моем приложении есть экран, на котором я использую ускорители. Я использую функциональную клавишу F3 для выполнения операции в моем приложении. Он работает нормально каждый раз, но когда я нажимаю любое текстовое поле на этом экране, функциональная клавиша не выполняется.

Вот код, в котором я устанавливаю ускоритель:

    scene.getAccelerators().put(
            new KeyCodeCombination(KeyCode.F3),
            new Runnable() {
                @Override
                public void run() {
                    // do sth here
                }
            }
    );

Когда я щелкаю свое текстовое поле, а затем нажимаю функциональную клавишу F3, это не работает. Кто-то знает решение?


person henriqueor    schedule 30.01.2015    source источник
comment
См. этот вопрос SO для лучшего ответа, который не требует изменения элемента управления: stackoverflow.com/questions/25397742/   -  person geometrikal    schedule 13.06.2017
comment
вроде исправлено в fx9, то есть акселераторы (в меню и вручную установленные) работают если textField сфокусирован   -  person kleopatra    schedule 28.11.2017


Ответы (4)


Это работает для меня с использованием Java 1.8.0_45. Однако я сталкиваюсь с аналогичной проблемой с редактируемым полем со списком.

Отредактировано:

При дальнейшем расследовании это, похоже, происходит и с текстовым полем. Я работал над этим, используя следующий пользовательский класс вместо текстового поля:

public class ShortcutFriendlyTextField extends TextField{

    public ShortcutFriendlyTextField() {
        super();
        addEventHandler(KeyEvent.KEY_RELEASED,new EventHandler<KeyEvent>() {

            @Override
            public void handle(KeyEvent event) {
                //handle shortcuts if defined
                Runnable r=getScene().getAccelerators().get(new KeyCodeCombination(event.getCode()));
                if(r!=null) {
                    r.run();  
                }
            }
        }); 
    }
}
person tkerman    schedule 01.05.2015

Этот ответ основан на tikerman. Я добавил код для обработки клавиш-модификаторов.

if (!event.getCode().isModifierKey()) {
    Consumer<KeyCombination.Modifier[]> runAccelerator = (modifiers) -> {
        Runnable r = getScene().getAccelerators().get(new KeyCodeCombination(event.getCode(), modifiers));
        if (r != null) {
            r.run();
        }
    };

    List<KeyCombination.Modifier> modifiers = new ArrayList<>();
    if (event.isControlDown()) modifiers.add(KeyCodeCombination.CONTROL_DOWN);
    if (event.isShiftDown()) modifiers.add(KeyCodeCombination.SHIFT_DOWN);
    if (event.isAltDown()) modifiers.add(KeyCodeCombination.ALT_DOWN);

    runAccelerator.apply(modifiers.toArray(new KeyCombination.Modifier[modifiers.size()]));
}

Изменить: исправить потребительскую орфографию.

person Melvic Ybanez    schedule 05.07.2015
comment
Это выглядит интересно, но правильный ли код? Кажется, что переменная modifier использовалась до определения? Кроме того, какова цель кода? Даже в более простой версии мои ускорители с модификаторами работают нормально (проверено на JavaFX 8). - person Suma; 01.04.2016
comment
Я ошибался насчет модификаторов - они плохо обрабатываются в другом коде, сама клавиша модификатора выдает исключение при попытке обработать ее освобождение. Тем не менее я убежден, что порядок кода неверен. - person Suma; 01.04.2016
comment
@Suma Первая переменная modifier является параметром лямбда-выражения. Другими словами, он является локальным для объекта runAccelerator. Это не относится к тому, что определено как List<KeyCombination.Modifier>. - person Melvic Ybanez; 02.04.2016
comment
Спасибо за объяснение, теперь я понял. - person Suma; 02.04.2016

Если у вас есть ускорители, настроенные в другом месте, например в MenuBar, использование некоторых других решений приведет к тому, что ярлык будет выполнен дважды.

В моем случае использование модификаторов с моим сочетанием клавиш (SHIFT + F3) работает, когда фокус находится в текстовой области, но не при использовании только акселератора, такого как просто F3.

Я настроил свой так, чтобы использовать обработчик событий только для ярлыков, которые не используют модификатор.

public  static final double JAVA_VERSION = Double.parseDouble(System.getProperty("java.specification.version"));
public static void makeInputFieldShortCutFriendly(Node node) {
    //this bug wasn't fixed until 9.0
    if (JAVA_VERSION < 9) {
        node.addEventHandler(KeyEvent.KEY_RELEASED, (KeyEvent event) -> {
            if (!event.getCode().isModifierKey()) {
                if (!event.isAltDown() && !event.isShiftDown() && !event.isAltDown()) {
                    Runnable r = node.getScene().getAccelerators().get(new KeyCodeCombination(event.getCode(), KeyCodeCombination.SHORTCUT_ANY));

                    if (r != null) {
                        r.run();
                    }
                }
            }
        });
    }
}

Редактировать: в Java 9 не было исправлено никаких ярлыков модификаторов. Учитывая популярность JDK 8 прямо сейчас, мы, вероятно, должны обеспечить некоторую обратную совместимость или попросить пользователей обновить там JRE до 9+.

person Adrian Elder    schedule 27.11.2017
comment
проблема вроде исправлена ​​в fx9, то есть ускорители (в меню и вручную установленные) работают если textField сфокусирован - person kleopatra; 28.11.2017

Если вы используете построитель JavaFx+Scene, то просто создайте функцию, которая перенаправляет все события в соответствующие функции, а затем добавляете эту функцию к каждому элементу сцены с событием OnKeyReleased.

person headathigh    schedule 22.07.2021