В настоящее время я использую 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) {
}
}
Да, но после нажатия кнопки я пытаюсь дождаться нажатия клавиши клавиатуры и, таким образом, изменю метку на эту конкретную клавишу клавиатуры. Изначально метка «Остановить горячую клавишу: F3», а после нажатия кнопки программа должна ждать, пока пользователь введет клавишу на своей клавиатуре, и метка должна соответственно измениться - «Остановить горячую клавишу: (ввод с клавиатуры)». . Я не уверен, как это сделать с помощью обработчика ключевых событий javafx.
«Да, но после того, как кнопка нажата, я пытаюсь дождаться нажатия клавиши клавиатуры и, таким образом, изменю метку на эту конкретную клавишу клавиатуры». Так что не так с тем, что я предложил?
Вероятно, мое ужасное понимание вашего ответа, мои извинения. Я совсем новичок в javafx. Не могли бы вы привести пример для вашего первого ответа?
Какова конечная цель? Ваше описание не соответствует стандартным представлениям о том, как работает интерфейс. Кнопки не ждут ввода: они нажаты, и пользователь ожидает, что действие, описанное текстом кнопки, будет выполнено, если позволяют условия (например, проверка может заблокировать действие). Я только что запустил NativeHookDemo
, чтобы посмотреть, что он может сделать помимо возможностей, предоставляемых JavaFX для прослушивания таких событий. ...
... Я был удивлен, что мне пришлось изменить настройки безопасности доступа к системе (macOS), чтобы позволить демо-версии управлять моим компьютером! Ой! Также заметил, что даже когда я печатал в другом приложении (например, в Сообщениях), демонстрация записывала нажатия клавиш. Не хорошо.
@pfurbacher Я не пытаюсь кодировать какие-то схематичные вещи, просто пытался сделать окно для своего автокликера...
Я не думаю, что вам вообще нужно привлекать сюда нативных ключевых слушателей. Обычный обработчик ключевых событий 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()
кнопки и отменить его регистрацию, когда кнопка теряет фокус.
Возможны и другие общие решения (не использующие встроенные прослушиватели ключей). Например: зарегистрируйте обработчик ключевого события в сцене, и в этом обработчике проверьте состояние вашего приложения (инкапсулированное в некоторые соответствующие переменные) и измените все, что нужно изменить (если что-то). В обработчиках действий кнопок обновите состояние приложения, чтобы при нажатии клавиши происходило правильное действие.
«Предполагается, что пользователь должен щелкнуть по нему один раз, и как только будет ввод, он изменит метку». Когда вы нажимаете кнопку, она получает фокус клавиатуры. Зачем вам возиться с
jnativehook
и т. д.? Разве недостаточно просто зарегистрировать обычный обработчик событий клавиши JavaFX (или фильтр) с помощью кнопки? Этот обработчик будет вызываться только в том случае, если кнопка имеет фокус.