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

时间:2014-11-27 11:32:27

标签: java swing

我正在制作一些可以模拟和读取原生输入事件的鼠标/键盘/像素类。这些是作为java.awt.Robot和JNativeHook的包装器实现的。它们旨在用作Mac上AutoHotKey或AutoIt的替代品。我在Windows 7 64位计算机上进行测试。

我的问题是,我无法弄清楚为什么JNativeHook的键盘监听器无法正常工作。我还没有去测试鼠标听众的工作情况。它可能与Swing和JNativeHook的多线程问题有关,但我没有排除库或构建版本的问题。

我的大部分代码都是直接来自示例页面。 JNativeHook使用鼠标/键盘的调试信息为Logger和控制台发送垃圾邮件,但它不会调用监听器。我使用下载页面中的最新jar以及Eclipse和最新的jdk / jre,除非安装出现了可怕的错误。

测试类

程序显示一个按钮和一个彩色面板。按下按钮,然后键入" 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();
            }
        });
    }
}

键类

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

1 个答案:

答案 0 :(得分:0)

我将jar版本从RC3切换到Beta2,它适用于Windows。 Beta2并没有在Mac上运行,但我认为RC 2或3可以。