尝试用JAVA读取滚动锁状态。

问题描述 投票:0回答:1

我有以下几行代码,我想用它们来读取滚动锁的状态。

当我的程序启动时,我得到了滚动锁的状态,但我希望得到实时状态。

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));
        }
    }

}

java multithreading jar automation awt
1个回答
2
投票

这是一个有趣的行为,正确地报告初始状态,但依赖于后续的事件处理(有一个聚焦的顶层窗口或托盘图标)来更新。

如果我们有办法将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);
        }
    }
}

0
投票

如果你想监听滚动锁的按键声,就可以实现一个 关键监听者 寻找 KeyEvent.VK_SCROLL_LOCK.

通常情况下,(也正是因为 getLockingKeyState() 方法),你将会监听其他事件(例如,按下updown方向键),然后查询滚动锁键的状态来决定如何解释该事件。但应该可以像其他按键一样监听滚动锁的按压。

我的笔记本键盘上没有滚动锁定键,但是当我运行了这个程序后,我就会发现我的键盘上有一个滚动锁定键。KeyEventDemo.java 例如,从链接的教程中,我看到它捕捉到了 KeyEvent.VK_CAPS_LOCK 事件;当Caps Lock开启时,"KEY PRESSED "事件会触发,当Caps Lock关闭时,"KEY RELEASED "事件会触发。滚动锁定也应该是类似的。

我在 KeyEventDemo.java's displayInfo() 方法来查看 "实时 "Caps Lock状态。

displayArea.append("Caps Lock: " +
    Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK) +
    newline);

如果你用同样的方法 VK_SCROLL_LOCK 当按下该键时,你应该看到滚动锁定状态的开启和关闭。

每当你调用 getLockingKeyState() 你得到的是 当前,该键的 "实时 "状态,所以只要你需要知道该键的状态时,就调用该方法。


0
投票

其实,我也遇到过类似的情况,我通过使用一个 机器人。 当你想知道卷轴锁是否开启,并获得正确的状态时,让机器人按下2次按钮。但是,(可能是一个bug),如果你立即这样做,状态就不正确。你将不得不添加一个延迟(不是人可以察觉的),以获得正确的状态。这意味着,你必须在一个后台线程中进行,而不是在EDT中进行,因为这会导致EDT冻结(当线程睡眠时,事件无法发生)。

请看这个例子(代码中的一些注释)。它总是给出正确的滚动锁定状态,即使窗口不在焦点中。另外,有一个全局的键监听器,所以你可以知道滚动锁是否被按下(但只有当窗口有焦点时才会触发)。

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();
        });
    }
}

在注释中的声明之后(它们应该存在于问题中),实现滚动锁是否为ONOFF的最好方法是使用 全能钥匙监听器. 当你的应用程序启动时,它将滚动锁定状态从 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 可变的。

© www.soinside.com 2019 - 2024. All rights reserved.