如何使KeyListener接受来自机器人的输入

时间:2018-08-14 22:36:20

标签: java jframe keylistener keyevent

此代码的主要目的是一种在JFrame中使用keyListeners的AutoHotKey。 AutoHotKey易于使用,并且可以提供更快的解决方案,但是我出于学习目的而编写此

我正在尝试使我的keyListeners(KeyPressed)之一从机器人keyPress而不是用户keyPress接收输入。我创建了一个Robot对象,并发送了keyPress和keyRelease,但是该程序仍在请求用户输入其他信息。

我要发生的是触发keyPress事件,并让keyListener将其作为用户的输入,并继续执行程序的其余部分,最终将其关闭。

当前代码:

public class Main extends JFrame implements KeyListener {

private static final long serialVersionUID = 7225065896901900132L;

/**
 * Aye, I do not recommend storing passwords as plain text if it is for
 * something important but here is this code anyway because i'm bored.
 * 
 * Also should not that using a AutoHotKey or any other macro program is way
 * easier but i'm using Java because learning amiright
 */

//declaring variables and objects
private static String fileName = "C:/users/21cra/Desktop/rmtinfo.txt";
private static Scanner SC;
private Robot robObject;

public static void main(String[] args) {

    //creates JFrame
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            Main frame = new Main();
            frame.setTitle("Copier");
            frame.setResizable(false);
            frame.setSize(0, 0);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);

        }
    });
}

public Main() {

    //add key listener for this JFrame
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);

    // try catch for forcing Escape key press
    try {
        robObject = new Robot();
        robObject.keyPress(KeyEvent.VK_ESCAPE);
        robObject.keyRelease(KeyEvent.VK_ESCAPE);
        System.out.println("press");
    } catch (AWTException e1) {
        e1.printStackTrace();
    }

}

@Override
public void keyPressed(KeyEvent e) {

    // declaring variables and objects
    String pass = null;
    File passFile = new File(fileName);

    // try catch for handling next key press
    // also copies the first line of any file

    try {
        SC = new Scanner(new File(fileName));
        pass = SC.next();

        int keyCode = e.getKeyCode();

        if (keyCode == KeyEvent.VK_ESCAPE) {

            StringSelection stringObj = new StringSelection(pass);
            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
            clipboard.setContents(stringObj, null);
            System.exit(0);
        }

        System.out.println(pass);

    } catch (Exception error) {

        System.out.println("Error " + error);

    }

}

@Override
public void keyTyped(KeyEvent e) {

}

@Override
public void keyReleased(KeyEvent e) {

}

}

1 个答案:

答案 0 :(得分:1)

因此,存在许多问题。为了使KeyListener生成键事件,其注册到的组件必须是可聚焦的并且具有键盘焦点。最好的时候,这是一件很难的事情。

您正在生成关键事件,然后该窗口将被实现(附加到本机同位体)并在屏幕上可见,这意味着KeyListener将无法对其进行响应。您需要等到窗口可见并在屏幕上处于活动状态。由于setVisible仅声明使窗口“应该”可见,因此不能保证该窗口将是活动的并且可用于处理输入事件。您需要某种方法来在setVisible和击键的产生之间进行延迟。

在这里类似第二个Thread可能有用...

Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {
        }
        // try catch for forcing Escape key press
        try {
            Robot robObject = new Robot();
            robObject.keyPress(KeyEvent.VK_ESCAPE);
            robObject.keyRelease(KeyEvent.VK_ESCAPE);
            System.out.println("press");
        } catch (AWTException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

    }
});
t.start();

有关更多详细信息,请参见Concurrency in Java

所以,真的很基础。它启动一个线程,等待一秒钟,然后触发按键事件。应该把工作做好,这有点脏。

nb:摆动是单线程的,不是线程安全的。永远不要从事件调度线程的上下文之外更新UI

由于KeyListener如此……令人烦恼,一个更好的解决方案可能是使用Key Bindings API,这将使您更好地控制应生成关键事件的焦点级别。 / p>

也许更像是...

import java.awt.AWTException;
import java.awt.BorderLayout;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Scanner;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

public class Main extends JFrame {

    private static final long serialVersionUID = 7225065896901900132L;

    /**
     * Aye, I do not recommend storing passwords as plain text if it is for
     * something important but here is this code anyway because i'm bored.
     *
     * Also should not that using a AutoHotKey or any other macro program is way
     * easier but im using Java because learning amiright
     */
    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                Main frame = new Main();
                frame.setTitle("Copier");
                frame.setResizable(false);
                frame.setSize(100, 100);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setVisible(true);

                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException ex) {
                        }
                        // try catch for forcing Escape key press
                        try {
                            Robot robObject = new Robot();
                            robObject.keyPress(KeyEvent.VK_ESCAPE);
                            robObject.keyRelease(KeyEvent.VK_ESCAPE);
                            System.out.println("press");
                        } catch (AWTException e1) {
                            // TODO Auto-generated catch block
                            e1.printStackTrace();
                        }

                    }
                });
                t.start();
            }
        });
    }

    public Main() {
        JPanel panel = new JPanel(new BorderLayout());
        InputMap inputMap = panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        ActionMap actionMap = panel.getActionMap();

        inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "escape");
        actionMap.put("escape", new EscapeAction());

        setContentPane(panel);
    }

    protected class EscapeAction extends AbstractAction {

        private final String fileName = "C:/users/21cra/Desktop/rmtinfo.txt";

        @Override
        public void actionPerformed(ActionEvent e) {
            String pass = null;
            File passFile = new File(fileName);
            try (Scanner scanner = new Scanner(new File(fileName))) {
                pass = scanner.next();

                StringSelection stringObj = new StringSelection(pass);
                Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                clipboard.setContents(stringObj, null);
                System.exit(0);

                System.out.println(pass);

            } catch (Exception error) {

                System.out.println("Error " + error);

            }
        }

    }

}