如何在JavaFX的密码字段上实现CAPS LOCK警报气泡?

时间:2018-08-02 17:22:34

标签: java javafx

我正在尝试在密码字段上实施大写锁定警报。如果大写锁定为开,则气泡将出现在密码字段下方。我进行了很多搜索,但没有找到如何在JavaFX的输入字段中实现这种冒泡的解决方案。我找到了一些用于获取大写锁定状态的源代码。

    boolean isOn=Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK);
scene.setOnKeyReleased( event -> {
            if ( event.getCode() == KeyCode.CAPS ) {
                System.out.println("Capslock pressed");
                System.out.println("Capslock state: " + isOn);
            }
        });

但是我的问题是如何在文本字段上实现气泡警报。 在这里,您可以看到我要做的事情。

enter image description here

如果您建议我一些新的JavaFX可能方法会很有帮助。是否有任何JavaFX库在输入字段上执行此类气泡警报?

2 个答案:

答案 0 :(得分:1)

JavaFX无法检测CapsLock。从理论上讲,您可以安装一个全场景的侦听器,但是当状态改变而其他应用程序具有焦点时,该侦听器将无法捕获。

混合AWT / Swing和JavaFX非常危险,因为它们每个都有自己的线程,几乎所有方法都必须在该线程上执行。由于仍然需要轮询CapsLock,因此使用javax.swing.Timer是有意义的,playground可以定期执行操作并确保操作在适当的线程(AWT事件分发线程)中运行:

BooleanProperty capsLockOn = new SimpleBooleanProperty();

EventQueue.invokeLater(() -> {
    Timer timer = new Timer(500, e -> {
        boolean state = Toolkit.getDefaultToolkit().getLockingKeyState(
            KeyEvent.VK_CAPS_LOCK);
        Platform.runLater(() -> capsLockOn.set(state));
    });
    timer.start();
    Platform.runLater(() -> {
        Window window = passwordField.getScene().getWindow();
        window.setOnShown(e -> EventQueue.invokeLater(timer::restart));
        window.setOnHidden(e -> EventQueue.invokeLater(timer::stop));
    });
});

Region message = new BorderPane(new Label("Caps Lock is on"));
message.setStyle(
    "-fx-background-color: #f4f4f4;" +
    "-fx-border-color: black;" +
    "-fx-border-width: 1px;" +
    "-fx-padding: 1em 1em 0.75em 1em;" +
    "-fx-shape: 'M 0 10 h 20 l 10 -10 l 10 10 h 150 v 90 h -190 z';"
);

Popup capsLockWarning = new Popup();
capsLockWarning.getContent().add(message);

capsLockOn.addListener((o, wasOn, on) -> {
    if (on) {
        Point2D location =
            passwordField.localToScreen(-15, passwordField.getHeight());
        capsLockWarning.show(passwordField,
            location.getX(), location.getY());
    } else {
        capsLockWarning.hide();
    }
});

答案 1 :(得分:1)

听起来您已经弄清楚如何获取输入状态,可以为监听器尝试类似的操作

public class Main extends Application {

    private Label capsLabel = new Label("Caps is ON");

    private boolean capsIsOn;

    @Override
    public void start(Stage stage) {
        System.out.println(Toolkit.getDefaultToolkit().getLockingKeyState(20));

        //Try adding this line to get state on startup
        capsLabel.setVisible(Toolkit.getDefaultToolkit().getLockingKeyState(20));

        TextField textField = new TextField();

        //Also try adding this line and to check again so when the field 
        //is selected it will check again
        textField.setOnMouseClicked(event -> capsLabel.setVisible(Toolkit.getDefaultToolkit().getLockingKeyState(20)));

        textField.setOnKeyReleased(keyEvent -> {
            if(keyEvent.getCode().toString().equals("CAPS")){
                capsIsOn = !capsIsOn;
                capsLabel.setVisible(capsIsOn);
            }
        });

        VBox vBox = new VBox();
        vBox.getChildren().addAll(textField, capsLabel);

        stage = new Stage();
        stage.setScene(new Scene(vBox));
        stage.show();
    }

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

或者,您可以在计时器上设置它,并让它不断地进行个人检查,我不喜欢不断使用计算机资源的想法,但是我的项目不是我的想法。