Как дождаться нажатия клавиши?

В настоящее время я использую jnativhook из: https://github.com/kwhat/jnativehook для прослушивания нативных ключей. Я пытался сделать кнопку, которая ожидает нажатия родной клавиши и устанавливает этот ввод в качестве новой горячей клавиши. Вот что я пробовал до сих пор, но когда пользователь щелкает по нему, ему приходится вводить ключ и снова нажимать кнопку. Предполагается, что пользователь может щелкнуть по нему один раз, и как только будет ввод, он изменит метку.

import com.github.kwhat.jnativehook.GlobalScreen;
import com.github.kwhat.jnativehook.NativeHookException;
import com.github.kwhat.jnativehook.keyboard.NativeKeyEvent;
import com.github.kwhat.jnativehook.keyboard.NativeKeyListener;
import com.github.kwhat.jnativehook.mouse.NativeMouseInputListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.animation.AnimationTimer;

public class HotKeyWindowController implements NativeKeyListener {
    @FXML
    private Label stopHotKeyLabel;
    @FXML
    private Label startHotKeyLabel;
    @FXML
    private Button stopHotKeyButton;
    @FXML
    private Button startHotKeyButton;
    private static String startKey = "F1";
    private static String stopKey = "F3";
    private static String key;


    public void nativeKeyPressed(NativeKeyEvent e) {

        key = NativeKeyEvent.getKeyText(e.getKeyCode());
    }
    public void stopHotKeyButtonClicked(ActionEvent actionEvent) {
        GlobalScreen.removeNativeKeyListener(new HelloApplication());
        GlobalScreen.addNativeKeyListener(new HotKeyWindowController());
        stopKey = key;
        stopHotKeyLabel.setText("Stop HotKey: " + stopKey);
        GlobalScreen.addNativeKeyListener(new HelloApplication());
        GlobalScreen.removeNativeKeyListener(new HotKeyWindowController());
    }

    public void startHotKeyButtonClicked(ActionEvent actionEvent) {

    }
}

«Предполагается, что пользователь должен щелкнуть по нему один раз, и как только будет ввод, он изменит метку». Когда вы нажимаете кнопку, она получает фокус клавиатуры. Зачем вам возиться с jnativehook и т. д.? Разве недостаточно просто зарегистрировать обычный обработчик событий клавиши JavaFX (или фильтр) с помощью кнопки? Этот обработчик будет вызываться только в том случае, если кнопка имеет фокус.

James_D 21.02.2023 20:45

Да, но после нажатия кнопки я пытаюсь дождаться нажатия клавиши клавиатуры и, таким образом, изменю метку на эту конкретную клавишу клавиатуры. Изначально метка «Остановить горячую клавишу: F3», а после нажатия кнопки программа должна ждать, пока пользователь введет клавишу на своей клавиатуре, и метка должна соответственно измениться - «Остановить горячую клавишу: (ввод с клавиатуры)». . Я не уверен, как это сделать с помощью обработчика ключевых событий javafx.

Leo 21.02.2023 21:18

«Да, но после того, как кнопка нажата, я пытаюсь дождаться нажатия клавиши клавиатуры и, таким образом, изменю метку на эту конкретную клавишу клавиатуры». Так что не так с тем, что я предложил?

James_D 21.02.2023 21:20

Вероятно, мое ужасное понимание вашего ответа, мои извинения. Я совсем новичок в javafx. Не могли бы вы привести пример для вашего первого ответа?

Leo 21.02.2023 21:22

Какова конечная цель? Ваше описание не соответствует стандартным представлениям о том, как работает интерфейс. Кнопки не ждут ввода: они нажаты, и пользователь ожидает, что действие, описанное текстом кнопки, будет выполнено, если позволяют условия (например, проверка может заблокировать действие). Я только что запустил NativeHookDemo, чтобы посмотреть, что он может сделать помимо возможностей, предоставляемых JavaFX для прослушивания таких событий. ...

pfurbacher 21.02.2023 21:35

... Я был удивлен, что мне пришлось изменить настройки безопасности доступа к системе (macOS), чтобы позволить демо-версии управлять моим компьютером! Ой! Также заметил, что даже когда я печатал в другом приложении (например, в Сообщениях), демонстрация записывала нажатия клавиш. Не хорошо.

pfurbacher 21.02.2023 21:35

@pfurbacher Я не пытаюсь кодировать какие-то схематичные вещи, просто пытался сделать окно для своего автокликера...

Leo 21.02.2023 21:46
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
7
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не думаю, что вам вообще нужно привлекать сюда нативных ключевых слушателей. Обычный обработчик ключевых событий JavaFX для кнопки будет вызываться только в том случае, если кнопка имеет фокус клавиатуры, что обычно происходит только при нажатии кнопки (но см. примечание позже). Таким образом, если вам нужна функциональность, чтобы изменить метку (и, предположительно, другие действия) при нажатии клавиши после нажатия кнопки, должно быть достаточно просто зарегистрировать обработчик события клавиши с помощью кнопки. Вот краткий пример:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

import java.io.IOException;

public class HelloApplication extends Application {
    @Override
    public void start(Stage stage) throws IOException {
        Label startHotkeyLabel = new Label("Start HotKey: F1");
        Label stopHotkeyLabel = new Label("Stop HotKey: F3");
        Button changeStartHotkey = new Button("Change start key");
        changeStartHotkey.setOnKeyReleased(e -> startHotkeyLabel.setText("Start HotKey: "+e.getCode()));
        Button changeStopHotkey = new Button("Change stop key");
        changeStopHotkey.setOnKeyReleased(e -> stopHotkeyLabel.setText("Stop HotKey: "+e.getCode()));
        GridPane grid = new GridPane();
        grid.setHgap(5);
        grid.setVgap(5);
        grid.setPadding(new Insets(10));
        grid.setAlignment(Pos.CENTER);
        TextField textField = new TextField();
        grid.add(textField, 0, 0, 2, 1);
        grid.add(changeStartHotkey, 0, 1);
        grid.add(startHotkeyLabel, 1, 1);
        grid.add(changeStopHotkey,0, 2);
        grid.add(stopHotkeyLabel, 1, 2);

        Scene scene = new Scene(grid);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch();
    }
}

Обратите внимание, что соответствующая «горячая клавиша» будет меняться каждый раз, когда кнопка находится в фокусе клавиатуры. Поэтому, если вы используете клавишу Tab для перемещения фокуса клавиатуры на одну из кнопок и нажимаете клавишу, соответствующая метка изменится. Это, вероятно, то, что вы хотите в любом случае; это было бы то, что ожидал бы пользователь. Однако, если вы этого не хотите, достаточно просто зарегистрировать обработчик ключевого события в обработчике onAction() кнопки и отменить его регистрацию, когда кнопка теряет фокус.


Возможны и другие общие решения (не использующие встроенные прослушиватели ключей). Например: зарегистрируйте обработчик ключевого события в сцене, и в этом обработчике проверьте состояние вашего приложения (инкапсулированное в некоторые соответствующие переменные) и измените все, что нужно изменить (если что-то). В обработчиках действий кнопок обновите состояние приложения, чтобы при нажатии клавиши происходило правильное действие.

Другие вопросы по теме