简体   繁体   English

JNativeHook键盘侦听器无法与我的Swing / GUI一起使用

[英]JNativeHook Keyboard listener isn't working with my Swing/GUI

I'm making some Mouse/Keyboard/Pixels classes that can simulate and read native input events. 我正在制作一些可以模拟和读取本机输入事件的Mouse / Keyboard / Pixels类。 These are implementated as a wrappers around java.awt.Robot and JNativeHook . 这些被实现为java.awt.Robot和JNativeHook的包装器。 They're intended to be used as replacements for AutoHotKey or AutoIt on a Mac. 它们打算用作Mac上AutoHotKey或AutoIt的替代品。 I'm doing my testing on a Windows 7 64bit machine. 我正在Windows 7 64位计算机上进行测试。

My problem is that I can't figure out why my keyboard listener for JNativeHook isn't working. 我的问题是我不知道为什么我的JNativeHook键盘监听器无法正常工作。 I haven't got around to testing if the Mouse listeners work yet. 我还没有测试Mouse侦听器是否可以正常工作。 It's possibly related to multi-threading issues with Swing and JNativeHook , but I haven't ruled out problems with the library or build version. 它可能与Swing和JNativeHook的多线程问题有关 ,但我没有排除库或构建版本的问题。

Most of my code is directly from the example page. 我的大部分代码直接来自示例页面。 JNativeHook spams the Logger and console with debug information for the mouse/keyboard but it doesn't call the listener. JNativeHook使用鼠标/键盘的调试信息向Logger和控制台发送垃圾邮件,但它不会调用侦听器。 I'm using the latest jar from the download page as well as Eclipse and the latest jdk/jre unless something went horribly wrong with the installs. 我使用的是下载页面上的最新jar以及Eclipse和最新的jdk / jre,除非安装过程出现严重错误。

Test class 测试班

The program displays a button and a colored panel. 该程序显示一个按钮和一个彩色面板。 Pressing the button and then typing "1" should change the panel's color to be the same as the pixel under my mouse cursor. 按下按钮,然后键入“ 1”,应将面板的颜色更改为与鼠标光标下方的像素相同的颜色。

import java.awt.AWTException;
import java.awt.Color;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.border.LineBorder;

import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;

@SuppressWarnings("serial")
public class Test extends JFrame implements NativeKeyListener, WindowListener {
    JPanel panel1 = null;
    JButton button1 = null;
    static final int PAD = 20;

    public Test() {
        // Disable console/log spam from JNativeHook
        /*
        LogManager.getLogManager().reset();
        Logger logger = Logger.getLogger(GlobalScreen.class.getPackage()
                .getName());
        logger.setLevel(Level.WARNING);
        */

        setTitle("Test");
        this.setLayout(null);
        this.setSize(300, 270);

        panel1 = new JPanel();
        panel1.setBackground(Color.RED);
        panel1.setSize(40, 40);
        panel1.setLocation(20, 20);
        panel1.setBorder(new LineBorder(Color.BLACK, 1));
        this.getContentPane().add(panel1);

        button1 = new JButton();
        button1.setText("Button1");
        button1.setSize(100, 20);
        button1.setLocation(20,
                panel1.getHeight() + panel1.getY() + PAD);
        button1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Keys.addKeyListener(new NativeKeyListener() {
                    public void nativeKeyPressed(NativeKeyEvent e) {
                        if(e.getKeyCode() == NativeKeyEvent.VC_1) {
                            Keys.removeKeyListener(this);
                            Point p = MouseInfo.getPointerInfo().getLocation();
                            try {
                                panel1.setBackground(new Robot().getPixelColor(p.x, p.y));
                            } catch (AWTException e1) {
                                e1.printStackTrace();
                            }
                            System.out.println("Listener Removed");
                        }
                        Toolkit.getDefaultToolkit().beep();
                        System.out.println("Pressed");
                    }

                    public void nativeKeyReleased(NativeKeyEvent e) {
                        System.out.println("Released");
                        Toolkit.getDefaultToolkit().beep();
                    }

                    public void nativeKeyTyped(NativeKeyEvent e) {
                        System.out.println("Typed");
                        Toolkit.getDefaultToolkit().beep();
                    } 
                });
                System.out.println("Button1");
                Toolkit.getDefaultToolkit().beep();
            }
        });
        this.getContentPane().add(button1);

        this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        this.addWindowListener(this);
        this.setVisible(true); // Display the window.
    }

    public void windowOpened(WindowEvent e) {
        // Initialize native hook
        try {
            GlobalScreen.registerNativeHook();
        } catch (NativeHookException ex) {
            System.err
                    .println("There was a problem registering the native hook.");
            System.err.println(ex.getMessage());
            ex.printStackTrace();
            System.exit(1);
        }

        GlobalScreen.getInstance().addNativeKeyListener(this);
    }

    public void windowClosed(WindowEvent e) {
        // Clean up the native hook
        GlobalScreen.unregisterNativeHook();
        System.runFinalization();
        System.exit(0);
    }

    public void windowClosing(WindowEvent e) {
        /* Unimplemented */
    }

    public void windowIconified(WindowEvent e) {
        /* Unimplemented */
    }

    public void windowDeiconified(WindowEvent e) {
        /* Unimplemented */
    }

    public void windowActivated(WindowEvent e) {
        /* Unimplemented */
    }

    public void windowDeactivated(WindowEvent e) {
        /* Unimplemented */
    }

    public void nativeKeyReleased(NativeKeyEvent e) {
        if (e.getKeyCode() == NativeKeyEvent.VC_SPACE) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JOptionPane.showMessageDialog(null,
                            "This will run on Swing's Event Dispatch Thread.");
                }
            });
        }
    }

    public void nativeKeyPressed(NativeKeyEvent e) {
        Toolkit.getDefaultToolkit().beep();
        /* Unimplemented */
    }

    public void nativeKeyTyped(NativeKeyEvent e) {
        Toolkit.getDefaultToolkit().beep();
        /* Unimplemented */
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Test();
            }
        });
    }
}

Keys class 按键类

import java.awt.AWTException;
import java.awt.AWTKeyStroke;
import java.awt.Robot;
import java.awt.event.KeyEvent;

import org.jnativehook.GlobalScreen;
import org.jnativehook.keyboard.NativeKeyListener;

public class Keys {
    protected static Robot r = null;

    static {
        try {
            r = new Robot();
        } catch (AWTException e) {
            e.printStackTrace();
        }
    }

    private Keys() {
    } // STATIC CLASS

    public static void setRobot(Robot r) {
        Keys.r = r;
    }

    public static Robot getRobot(Robot r) {
        return r;
    }

    /**
     * Sets the delay between each key Press/Release.
     * 
     * @param ms
     *            Number of milliseconds to delay. Zero removes any delay.
     */
    public static void setDelay(int ms) {
        r.setAutoDelay(ms);
    }

    /**
     * @param keycode
     *            Key to send, for example KeyEvent.VK_0 for the 0 key.
     */
    public static void send(int keycode) {
        r.keyPress(keycode);
        r.keyRelease(keycode);
    }

    /**
     * @param keycode
     *            Key to send, for example KeyEvent.VK_0 for the 0 key.
     */
    public static void press(int keycode) {
        r.keyPress(keycode);
    }

    /**
     * @param keycode
     *            Key to send, for example KeyEvent.VK_0 for the 0 key.
     */
    public static void release(int keycode) {
        r.keyRelease(keycode);
    }

    public static void send(char c) {
        String str = "" + c;
        send(str);
    }

    /**
     * Doesn't support ALT, CTRL, NUMLOCK, or CAPSLOCK. Might not support every
     * key.
     * 
     * @param str
     *            The string to simulate typing.
     */
    public static void send(String str) {
        boolean shiftOn = false;
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            int keycode = AWTKeyStroke.getAWTKeyStroke(c).getKeyCode();
            boolean isLower = Character.isLowerCase(c);
            if (shiftOn) {
                if (Character.isLowerCase(c)) {
                    r.keyRelease(KeyEvent.VK_SHIFT);
                    shiftOn = false;
                }
            } else if (!isLower) {
                r.keyPress(KeyEvent.VK_SHIFT);
                shiftOn = true;
            }
            r.keyPress(keycode);
            r.keyRelease(keycode);
        }
        if (shiftOn) {
            r.keyRelease(KeyEvent.VK_SHIFT);
        }
    }

    public static void addKeyListener(NativeKeyListener listener) {
        GlobalScreen.getInstance().addNativeKeyListener(listener);
    }

    public static void removeKeyListener(NativeKeyListener listener) {
        GlobalScreen.getInstance().removeNativeKeyListener(listener);
    }
}

I switched the jar build from RC3 to Beta2 and it works for Windows. 我将jar版本从RC3切换到Beta2,它适用于Windows。 Beta2 didn't work on Mac but I think RC 2 or 3 did. Beta2在Mac上不起作用,但我认为RC 2或3可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM