尝试使用 JAVA 读取 Scroll Lock 状态
Trying to read Scroll Lock status using JAVA
我有以下几行代码,我正在使用这些代码行来尝试读取滚动锁定的状态。
当我的程序启动时,我得到滚动锁定的状态。
但是我愿意实时获取状态。
请指导以下
package assignment;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import org.omg.PortableServer.THREAD_POLICY_ID;
public class ScrollLockOnOff {
public static void main(String[] args) throws InterruptedException
{
while(true)
{
Thread.sleep(1000);
Toolkit toolkit=Toolkit.getDefaultToolkit();
System.out.println(toolkit.getLockingKeyState(KeyEvent.VK_SCROLL_LOCK));
}
}
}
如果你想监听 scroll-lock 的按键执行 key listener 寻找 KeyEvent.VK_SCROLL_LOCK
.
通常(以及 getLockingKeyState()
方法的原因)你会监听其他事件(例如 up/down 箭头键按下)然后查询滚动锁定键的状态决定如何解释该事件。但是应该可以像任何其他键一样监听滚动锁定按下。
我的笔记本电脑键盘上没有滚动锁定键,但是当我 运行 来自链接教程的 KeyEventDemo.java
示例时,我看到它捕获了 KeyEvent.VK_CAPS_LOCK
事件; "KEY PRESSED" 事件在大写锁定打开时触发,"KEY RELEASED" 事件在关闭时触发。 Scroll Lock 的行为应该类似。
我在 KeyEventDemo.java
的 displayInfo()
方法末尾添加了以下行以查看 "realtime" Caps Lock 状态:
displayArea.append("Caps Lock: " +
Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK) +
newline);
如果您对 VK_SCROLL_LOCK
执行相同的操作,您应该会看到滚动锁定状态在按下键时打开和关闭。
每当您调用 getLockingKeyState()
时,您都会获得该键的 当前 、"real-time" 状态,因此只要您需要知道就调用该方法密钥的状态。
这是一个有趣的行为,正确报告初始状态但依赖于后续事件处理(具有聚焦的顶级 window 或托盘图标)进行更新。
如果我们有办法将 AWT 重置为初始状态,它应该可以解决问题。如果我们没有发现这种可能性,直接的解决方法是 运行 一个新的 JVM。由于具有相同属性的新 JVM 将使用缓存甚至共享内存中的资源,因此开销比听起来要小得多。每秒执行一次动作没问题:
public class ScrollLockOnOff {
public static void main(String[] args)
throws InterruptedException, AWTException, IOException {
if(args.length == 1 && args[0].equals("VK_SCROLL_LOCK")) {
System.exit(Toolkit.getDefaultToolkit()
.getLockingKeyState(KeyEvent.VK_SCROLL_LOCK)? KeyEvent.VK_SCROLL_LOCK: 0);
return;
}
ProcessBuilder b = new ProcessBuilder(
Paths.get(System.getProperty("java.home"), "bin", "java").toString(),
"-classpath", System.getProperty("java.class.path"),
ScrollLockOnOff.class.getName(), "VK_SCROLL_LOCK"
).inheritIO();
while(true) {
Thread.sleep(1000);
int state = b.start().waitFor();
if(state != 0 && state != KeyEvent.VK_SCROLL_LOCK) {
System.err.println("failed");
break;
}
System.out.println(state == KeyEvent.VK_SCROLL_LOCK);
}
}
}
实际上,我遇到过类似的事情,我用 Robot. 解决了当你想知道滚动锁是否打开,并获得它的正确状态时,让机器人 press/release按钮 2 次。但是,(可能是一个错误左右),如果您立即执行此操作,状态将不正确。您将不得不添加延迟(不是人类可察觉的)以获得正确的状态。这意味着,您必须在后台线程中执行此操作,而不是在 EDT 中执行,因为这会导致 EDT 冻结(当线程休眠时,事件无法发生)。
查看此示例(代码中的一些注释)。它总是给出滚动锁定的正确状态,即使 window 不在焦点上。此外,还有一个全局键侦听器,因此您知道是否按下了滚动锁定(但仅在 window 获得焦点时触发)。
public class ScrollLockDetection {
private static final int SCROLL_LOCK = KeyEvent.VK_SCROLL_LOCK;
private JFrame frame;
public ScrollLockDetection() {
frame = new JFrame();
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addWindowFocusListener(new WindowAdapter() {
@Override
public void windowGainedFocus(WindowEvent e) {
showScrollLockStatus();
}
});
registerGlobalScrollLockListener();
frame.setVisible(true);
}
private void registerGlobalScrollLockListener() {
Toolkit.getDefaultToolkit().addAWTEventListener(event -> {
if (event instanceof KeyEvent) {
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getID() == KeyEvent.KEY_RELEASED && keyEvent.getKeyCode() == KeyEvent.VK_SCROLL_LOCK) {
showScrollLockStatus();
}
}
}, AWTEvent.KEY_EVENT_MASK);
}
private void showScrollLockStatus() {
ScrollLockDetector scrollLockDetector = new ScrollLockDetector(b -> {
System.out.println("Scroll lock ON: " + b);
});
scrollLockDetector.execute();
}
class ScrollLockDetector extends SwingWorker<Boolean, Void> {
private Consumer<Boolean> consumer;
public ScrollLockDetector(Consumer<Boolean> consumer) {
this.consumer = consumer;
}
@Override
protected Boolean doInBackground() throws Exception {
//First we have to remove all global key listeners so the robot does not fire them
Toolkit toolkit = Toolkit.getDefaultToolkit();
AWTEventListener[] globalKeyListeners = toolkit.getAWTEventListeners(AWTEvent.KEY_EVENT_MASK);
while (toolkit.getAWTEventListeners(AWTEvent.KEY_EVENT_MASK).length > 0)
toolkit.removeAWTEventListener(toolkit.getAWTEventListeners(AWTEvent.KEY_EVENT_MASK)[0]);
Robot robot = new Robot();
robot.keyPress(SCROLL_LOCK);
robot.keyRelease(SCROLL_LOCK);
Thread.sleep(3);
robot.keyPress(SCROLL_LOCK);
robot.keyRelease(SCROLL_LOCK);
Thread.sleep(3);
//Re-add the global key listeners
Stream.of(globalKeyListeners).forEach(listener -> toolkit.addAWTEventListener(listener, AWTEvent.KEY_EVENT_MASK));
return toolkit.getLockingKeyState(SCROLL_LOCK);
}
@Override
protected void done() {
try {
Boolean isScrollLockOn = get();
consumer.accept(isScrollLockOn);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new ScrollLockDetection();
});
}
}
注释中声明后(有问题应该存在),实现滚动锁是否为ON/OFF的最好方法是使用a global key listener。当您的应用程序启动时,它会从 getLockingKeyState
获取滚动锁定状态,然后每次按下滚动锁定时,您都会更改它。
查看这个完整示例:
public class GlobalKeyListenerExample implements NativeKeyListener {
private static boolean scrollLock;
@Override
public void nativeKeyPressed(NativeKeyEvent e) {
}
@Override
public void nativeKeyReleased(NativeKeyEvent e) {
if (e.getKeyCode() == NativeKeyEvent.VC_SCROLL_LOCK) {
scrollLock = !scrollLock;
System.out.println("Scroll lock is:" + (scrollLock ? "ON" : "OFF"));
}
}
@Override
public void nativeKeyTyped(NativeKeyEvent e) {
}
public static void main(String[] args) {
try {
scrollLock = Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_SCROLL_LOCK);
System.out.println("Initial state of scrollock: " + (scrollLock ? "ON" : "OFF"));
GlobalScreen.registerNativeHook();
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.WARNING);
// Don't forget to disable the parent handlers.
logger.setUseParentHandlers(false);
// Don't forget to disable the parent handlers.
} catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
GlobalScreen.addNativeKeyListener(new GlobalKeyListenerExample());
}
}
现在,要检查滚动锁定是否打开,您只需检查 scrollLock
变量。
我有以下几行代码,我正在使用这些代码行来尝试读取滚动锁定的状态。
当我的程序启动时,我得到滚动锁定的状态。 但是我愿意实时获取状态。 请指导以下
package assignment;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import org.omg.PortableServer.THREAD_POLICY_ID;
public class ScrollLockOnOff {
public static void main(String[] args) throws InterruptedException
{
while(true)
{
Thread.sleep(1000);
Toolkit toolkit=Toolkit.getDefaultToolkit();
System.out.println(toolkit.getLockingKeyState(KeyEvent.VK_SCROLL_LOCK));
}
}
}
如果你想监听 scroll-lock 的按键执行 key listener 寻找 KeyEvent.VK_SCROLL_LOCK
.
通常(以及 getLockingKeyState()
方法的原因)你会监听其他事件(例如 up/down 箭头键按下)然后查询滚动锁定键的状态决定如何解释该事件。但是应该可以像任何其他键一样监听滚动锁定按下。
我的笔记本电脑键盘上没有滚动锁定键,但是当我 运行 来自链接教程的 KeyEventDemo.java
示例时,我看到它捕获了 KeyEvent.VK_CAPS_LOCK
事件; "KEY PRESSED" 事件在大写锁定打开时触发,"KEY RELEASED" 事件在关闭时触发。 Scroll Lock 的行为应该类似。
我在 KeyEventDemo.java
的 displayInfo()
方法末尾添加了以下行以查看 "realtime" Caps Lock 状态:
displayArea.append("Caps Lock: " +
Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK) +
newline);
如果您对 VK_SCROLL_LOCK
执行相同的操作,您应该会看到滚动锁定状态在按下键时打开和关闭。
每当您调用 getLockingKeyState()
时,您都会获得该键的 当前 、"real-time" 状态,因此只要您需要知道就调用该方法密钥的状态。
这是一个有趣的行为,正确报告初始状态但依赖于后续事件处理(具有聚焦的顶级 window 或托盘图标)进行更新。
如果我们有办法将 AWT 重置为初始状态,它应该可以解决问题。如果我们没有发现这种可能性,直接的解决方法是 运行 一个新的 JVM。由于具有相同属性的新 JVM 将使用缓存甚至共享内存中的资源,因此开销比听起来要小得多。每秒执行一次动作没问题:
public class ScrollLockOnOff {
public static void main(String[] args)
throws InterruptedException, AWTException, IOException {
if(args.length == 1 && args[0].equals("VK_SCROLL_LOCK")) {
System.exit(Toolkit.getDefaultToolkit()
.getLockingKeyState(KeyEvent.VK_SCROLL_LOCK)? KeyEvent.VK_SCROLL_LOCK: 0);
return;
}
ProcessBuilder b = new ProcessBuilder(
Paths.get(System.getProperty("java.home"), "bin", "java").toString(),
"-classpath", System.getProperty("java.class.path"),
ScrollLockOnOff.class.getName(), "VK_SCROLL_LOCK"
).inheritIO();
while(true) {
Thread.sleep(1000);
int state = b.start().waitFor();
if(state != 0 && state != KeyEvent.VK_SCROLL_LOCK) {
System.err.println("failed");
break;
}
System.out.println(state == KeyEvent.VK_SCROLL_LOCK);
}
}
}
实际上,我遇到过类似的事情,我用 Robot. 解决了当你想知道滚动锁是否打开,并获得它的正确状态时,让机器人 press/release按钮 2 次。但是,(可能是一个错误左右),如果您立即执行此操作,状态将不正确。您将不得不添加延迟(不是人类可察觉的)以获得正确的状态。这意味着,您必须在后台线程中执行此操作,而不是在 EDT 中执行,因为这会导致 EDT 冻结(当线程休眠时,事件无法发生)。
查看此示例(代码中的一些注释)。它总是给出滚动锁定的正确状态,即使 window 不在焦点上。此外,还有一个全局键侦听器,因此您知道是否按下了滚动锁定(但仅在 window 获得焦点时触发)。
public class ScrollLockDetection {
private static final int SCROLL_LOCK = KeyEvent.VK_SCROLL_LOCK;
private JFrame frame;
public ScrollLockDetection() {
frame = new JFrame();
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addWindowFocusListener(new WindowAdapter() {
@Override
public void windowGainedFocus(WindowEvent e) {
showScrollLockStatus();
}
});
registerGlobalScrollLockListener();
frame.setVisible(true);
}
private void registerGlobalScrollLockListener() {
Toolkit.getDefaultToolkit().addAWTEventListener(event -> {
if (event instanceof KeyEvent) {
KeyEvent keyEvent = (KeyEvent) event;
if (keyEvent.getID() == KeyEvent.KEY_RELEASED && keyEvent.getKeyCode() == KeyEvent.VK_SCROLL_LOCK) {
showScrollLockStatus();
}
}
}, AWTEvent.KEY_EVENT_MASK);
}
private void showScrollLockStatus() {
ScrollLockDetector scrollLockDetector = new ScrollLockDetector(b -> {
System.out.println("Scroll lock ON: " + b);
});
scrollLockDetector.execute();
}
class ScrollLockDetector extends SwingWorker<Boolean, Void> {
private Consumer<Boolean> consumer;
public ScrollLockDetector(Consumer<Boolean> consumer) {
this.consumer = consumer;
}
@Override
protected Boolean doInBackground() throws Exception {
//First we have to remove all global key listeners so the robot does not fire them
Toolkit toolkit = Toolkit.getDefaultToolkit();
AWTEventListener[] globalKeyListeners = toolkit.getAWTEventListeners(AWTEvent.KEY_EVENT_MASK);
while (toolkit.getAWTEventListeners(AWTEvent.KEY_EVENT_MASK).length > 0)
toolkit.removeAWTEventListener(toolkit.getAWTEventListeners(AWTEvent.KEY_EVENT_MASK)[0]);
Robot robot = new Robot();
robot.keyPress(SCROLL_LOCK);
robot.keyRelease(SCROLL_LOCK);
Thread.sleep(3);
robot.keyPress(SCROLL_LOCK);
robot.keyRelease(SCROLL_LOCK);
Thread.sleep(3);
//Re-add the global key listeners
Stream.of(globalKeyListeners).forEach(listener -> toolkit.addAWTEventListener(listener, AWTEvent.KEY_EVENT_MASK));
return toolkit.getLockingKeyState(SCROLL_LOCK);
}
@Override
protected void done() {
try {
Boolean isScrollLockOn = get();
consumer.accept(isScrollLockOn);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new ScrollLockDetection();
});
}
}
注释中声明后(有问题应该存在),实现滚动锁是否为ON/OFF的最好方法是使用a global key listener。当您的应用程序启动时,它会从 getLockingKeyState
获取滚动锁定状态,然后每次按下滚动锁定时,您都会更改它。
查看这个完整示例:
public class GlobalKeyListenerExample implements NativeKeyListener {
private static boolean scrollLock;
@Override
public void nativeKeyPressed(NativeKeyEvent e) {
}
@Override
public void nativeKeyReleased(NativeKeyEvent e) {
if (e.getKeyCode() == NativeKeyEvent.VC_SCROLL_LOCK) {
scrollLock = !scrollLock;
System.out.println("Scroll lock is:" + (scrollLock ? "ON" : "OFF"));
}
}
@Override
public void nativeKeyTyped(NativeKeyEvent e) {
}
public static void main(String[] args) {
try {
scrollLock = Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_SCROLL_LOCK);
System.out.println("Initial state of scrollock: " + (scrollLock ? "ON" : "OFF"));
GlobalScreen.registerNativeHook();
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.WARNING);
// Don't forget to disable the parent handlers.
logger.setUseParentHandlers(false);
// Don't forget to disable the parent handlers.
} catch (NativeHookException ex) {
System.err.println("There was a problem registering the native hook.");
System.err.println(ex.getMessage());
System.exit(1);
}
GlobalScreen.addNativeKeyListener(new GlobalKeyListenerExample());
}
}
现在,要检查滚动锁定是否打开,您只需检查 scrollLock
变量。