【问题标题】:Caps lock detection returns false value after refocus重新聚焦后大写锁定检测返回错误值
【发布时间】:2019-08-16 05:47:35
【问题描述】:

我有 JFrame,它必须检测大写锁定是打开还是关闭。如果我关注窗口一切正常,程序会通过 KeyListener 检测大写锁定状态的变化。当窗口最小化时,我无法检查大写锁定状态,所以我在用户重新聚焦窗口后检查状态。但随后检查返回我得到的最后一个大写锁定状态,而不是当前状态。

JFrame frame;

public example() {
    frame = new JFrame();
    frame.setSize(400, 400);
    frame.setVisible(true);

    frame.addWindowFocusListener(new WindowFocusListener() {
        @Override
        public void windowGainedFocus(WindowEvent e) {
            System.out.println("Caps Lock Status: " + Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK));
        }

        @Override
        public void windowLostFocus(WindowEvent e) {
            // nothing to do
        }
    });

}

如果我的大写锁定在窗口打开时关闭,而我在窗口未聚焦时打开大写锁定。然后,我期望在窗口重新聚焦后程序会得到一个真实的结果。

感谢各种建议,谢谢!

【问题讨论】:

  • 能否请您告诉我们您的操作系统是什么,您的 Java 版本是什么?
  • @GeorgeZ。我可以在 Windows 7/10 上产生这种行为,我的 Java 版本是 8。
  • @camickr 我无法重现您所附问题中描述的行为。如果窗口聚焦,一切正常,检测和行为都很好。如果我更改了大写锁定状态,而窗口未获得焦点,则检查将返回窗口未获得焦点之前的最后一个大写锁定状态。
  • 请问为什么需要检测 CAPS LOCK 何时开启?我的意思是也许还有另一种方法可以做你想做的事......

标签: java swing


【解决方案1】:

正如@camickr 在评论部分正确指出的那样,它与错误有关。可能使用 Windows 工具包。我尝试了一些事情来完成这项工作,唯一稳定的(测试了大约 100 次)是按下/取消按下 CAPS LOCK 2 次(一次更改其状态,一次将其恢复),其中一些 sleep 时间介于和然后从工具包中询问价值。为了实现这一点(让线程休眠),我们需要使用SwingWorker。我创建了一个 SwingWorker 类,它接受 Consumer<Boolean> 参数并在完成时接受它。消费者中的Boolean 值表示大写锁定是否打开/关闭。

看看:

public class CapsLockDetectWorker extends SwingWorker<Boolean, Void> {
    private Consumer<Boolean> consumer;
    private static final int CAPS_LOCK = KeyEvent.VK_CAPS_LOCK;

    public CapsLockDetectWorker(Consumer<Boolean> consumer) {
        this.consumer = consumer;
    }

    @Override
    protected Boolean doInBackground() throws Exception {
        Robot robot = new Robot();
        robot.keyPress(CAPS_LOCK);
        robot.keyRelease(CAPS_LOCK);
        Thread.sleep(3);
        robot.keyPress(CAPS_LOCK);
        robot.keyRelease(CAPS_LOCK);
        Thread.sleep(3);
        return Toolkit.getDefaultToolkit().getLockingKeyState(CAPS_LOCK);
    }

    @Override
    protected void done() {
        try {
            Boolean isCapsOn = get();
            consumer.accept(isCapsOn);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}

以及如何使用它的示例:

public class CapsLockDetection {
    private JFrame frame;

    public CapsLockDetection() {
        frame = new JFrame();
        frame.setSize(400, 400);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.addWindowFocusListener(new WindowFocusListener() {
            @Override
            public void windowGainedFocus(WindowEvent e) {
                new CapsLockDetectWorker(b -> {
                    System.out.println("ENABLED CAPS LOCK:" + b);
                }).execute();
            }

            @Override
            public void windowLostFocus(WindowEvent e) {
                // nothing to do
            }
        });

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new CapsLockDetection();
        });
    }
}

当然,如果您的计算机有一个带指示灯的caps lock 按钮(或者您的键盘中某处有一个),您会看到它闪烁(关闭/打开)...

我知道这看起来很傻,但我不认为你会找到更好的东西。

【讨论】:

    猜你喜欢
    • 2011-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    相关资源
    最近更新 更多