Toolkit.getDefaultToolkit().getLockingKeyState(...) 在程序执行期间从不更新

2022-01-13 00:00:00 keyboard java swing awt

我的问题是 Toolkit.getDefaultToolkit().getLockingKeyState(...) 永远不会更新.它在我第一次查询时正确报告,然后当我使用键盘更改状态时,更改永远不会反映.

I have the problem that Toolkit.getDefaultToolkit().getLockingKeyState(...) never updates. It reports correctly the first time I query it, then when I change the state using keyboard, the change is never reflected.

这是设计使然(API 文档中似乎并非如此)、错误还是我的代码有问题?

Is this by design (doesn't seem so in the API doc), a bug, or is there something with my code?

这里有一个简短的、独立的示例来演示该问题:

Here's a short, self-contained example to demonstrate the issue:

public class LockingStateIssue {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override public void run() {
                if (Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_NUM_LOCK)) {
                    System.out.print("*");
                } else {
                    System.out.print(".");
                }
            }
        }, 0, 200);
    }
}

在我的 Windows 机器上使用 Java 1.7.0_45 运行时,它会打印 .......********* 取决于 num lock 键的初始状态,但绝不会像我期望的那样混合 ..**.** 在切换按钮时.

When run, on my Windows machine, using Java 1.7.0_45, it prints either ....... or ********* depending on the initial state of the num lock key, but never a mix like ..**.** like I expect it to, when toggling the button.

推荐答案

  1. 没有 可见的 Java 容器 并且在窗口中也有焦点,KeyLoggers 在 Java 中被阻止,

  1. there isn't a correct way in plain Java without visible Java container and with focus in windows too, KeyLoggers are blocked in Java,

(可能不是主要问题,但也不会打印任何内容)来自 util.Timer 的循环已超出 EDT,更多内容请参见 Swing 中的并发性,Toolkit 来自 AWT 包,EDT 问题也适用于大多数 AWT 包

(could not be main issue, but nothing will be printed too) loop from util.Timer is out of EDT, more in Concurency in Swing, Toolkit is from AWT package, EDT issue is valid for most of AWT packages too

为我工作(在满足前两点的情况下,要求..),用于测试目的,在此程序执行期间尝试将焦点移至 Windows 操作系统中的另一个活动窗口

work for me (in the case that previous two points, requirements are met..), for testing purpose to try move focus to another active window in Windows OS durring this program execution

代码

import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFrame;

public class ToolkitAndNumLock {

    private javax.swing.Timer timer = null;
    private JFrame frame = new JFrame();

    public ToolkitAndNumLock() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        frame.setVisible(true);
        start();
        //uncomment Toolkit.getXxx listening a KeyEvents, you can (start();) block SwingTimer 
        //Toolkit.getDefaultToolkit().addAWTEventListener(listener, AWTEvent.KEY_EVENT_MASK);
    }
    AWTEventListener listener = new AWTEventListener() {
        @Override
        public void eventDispatched(AWTEvent event) {
            if (event instanceof KeyEvent) {
                KeyEvent ke = (KeyEvent) event;
                if (ke.getID() == KeyEvent.KEY_PRESSED) {
                    if (ke.getKeyCode() == KeyEvent.VK_CAPS_LOCK) {
                        System.out.println("CapsLock Pressed");
                    }
                    if (ke.getKeyCode() == KeyEvent.VK_SCROLL_LOCK) {
                        System.out.println("ScrollLock Pressed");
                    }
                    if (ke.getKeyCode() == KeyEvent.VK_NUM_LOCK) {
                        System.out.println("NumLock Pressed");
                    }
                }
            }
        }
    };

    private void start() {
        timer = new javax.swing.Timer(2500, updateCol());
        timer.setRepeats(true);
        timer.start();
    }

    public Action updateCol() {
        return new AbstractAction("text load action") {
            private static final long serialVersionUID = 1L;
            private Boolean bol = true;

            @Override
            public void actionPerformed(ActionEvent e) {
                if (Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_NUM_LOCK)) {
                    System.out.println("true");
                } else {
                    System.out.println("false");
                }
                if (bol) {
                    Toolkit.getDefaultToolkit().setLockingKeyState(KeyEvent.VK_NUM_LOCK, true);
                } else {
                    Toolkit.getDefaultToolkit().setLockingKeyState(KeyEvent.VK_NUM_LOCK, false);
                }
                bol = !bol;
            }
        };
    }

    public static void main(String args[]) {
        Runnable runner = new Runnable() {
            @Override
            public void run() {
                new ToolkitAndNumLock();
            }
        };
        EventQueue.invokeLater(runner);
    }
}

相关文章