Попытка прочитать состояние Scroll Lock, используя JAVA - PullRequest
2 голосов
/ 22 апреля 2020

У меня есть следующие строки кода, с помощью которых я пытаюсь прочитать состояние блокировки прокрутки.

Я получаю состояние блокировки прокрутки при запуске моей программы. Однако я готов получить статус в реальном времени. Пожалуйста, руководство по ниже

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

}

Ответы [ 3 ]

2 голосов
/ 06 мая 2020

Это интересное поведение - правильно сообщать о начальном состоянии, но зависеть от последующей обработки событий (с выделенным окном верхнего уровня или значком в трее) для обновлений.

Если бы у нас был способ сбросить 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 голосов
/ 07 мая 2020

На самом деле, я столкнулся с чем-то похожим, и я решил с помощью робота . Когда вы хотите узнать, включена ли блокировка прокрутки, и получить правильный статус, позвольте роботу нажать / отпустить кнопку. Кнопка 2 раза. Тем не менее, (возможно, ошибка или около того), статус не является правильным, если вы делаете это мгновенно. Вам нужно будет добавить задержку (не заметную человеку), чтобы получить правильный статус. Это означает, что вам придется делать это в фоновом потоке, а не в 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();
        });
    }
}

После объявлений в комментариях (они должны существовать в вопрос), лучший способ добиться включения / выключения блокировки прокрутки - использовать слушатель глобального ключа . Когда ваше приложение запускается, оно принимает состояние блокировки прокрутки с 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.

0 голосов
/ 02 мая 2020

Если вы хотите прослушивать нажатия клавиш прокрутки с блокировкой, используйте клавишный прослушиватель , ищущий KeyEvent.VK_SCROLL_LOCK.

Как правило (и причину использования метода getLockingKeyState()), вы ' будет прослушивать другие события (например, нажатия клавиш со стрелками вверх / вниз), а затем запрашивать состояние клавиши блокировки прокрутки, чтобы решить, как интерпретировать это событие. Но должна быть возможность прослушивания нажатий с блокировкой прокрутки, как и любой другой клавиши.

У меня нет клавиши блокировки прокрутки на клавиатуре моего ноутбука, но когда я запускаю пример KeyEventDemo.java из связанный учебник, я вижу, он захватывает KeyEvent.VK_CAPS_LOCK событий; событие «KEY PRESSED» срабатывает, когда Caps Lock включен, а событие «KEY RELEASED» срабатывает, когда оно выключено. Блокировка прокрутки должна вести себя аналогично.

Я добавил следующую строку в конец KeyEventDemo.java displayInfo() метода, чтобы увидеть состояние «Caps Lock» в реальном времени:

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

Если вы делаете то же самое с VK_SCROLL_LOCK, вы должны видеть, что состояние блокировки прокрутки включается и выключается при нажатии клавиши.

Всякий раз, когда вы звоните getLockingKeyState(), вы получаете текущий статус этого ключа в режиме реального времени, поэтому просто вызывайте этот метод всякий раз, когда вам нужно узнать статус ключа.

...