如何让 KeyListener 接受 Robot 的输入
How to make KeyListener accept input from Robot
这段代码的主要目的是一种在 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) {
}
}
因此,存在许多问题。为了让 KeyListener
生成按键事件,它注册到的组件必须是可聚焦的并且具有键盘焦点。这在最好的时候也是一件很难管理的事情。
在实现 window 并在屏幕上可见之前,您正在生成关键事件,这意味着 KeyListener
将无法响应他们。您需要等到 window 在屏幕上可见并处于活动状态。由于 setVisible
只是声明 window "should" 可见,因此无法保证 window 将处于活动状态并可用于处理输入事件。您需要一些方法在 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: Swing 是单线程的,不是线程安全的。永远不要从事件调度线程
的上下文之外更新UI
因为 KeyListener
太……烦人了,更好的解决方案可能是使用 Key Bindings API,这将使您更好地控制应该生成关键事件的焦点级别.
也许更像...
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);
}
}
}
}
这段代码的主要目的是一种在 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) {
}
}
因此,存在许多问题。为了让 KeyListener
生成按键事件,它注册到的组件必须是可聚焦的并且具有键盘焦点。这在最好的时候也是一件很难管理的事情。
在实现 window 并在屏幕上可见之前,您正在生成关键事件,这意味着 KeyListener
将无法响应他们。您需要等到 window 在屏幕上可见并处于活动状态。由于 setVisible
只是声明 window "should" 可见,因此无法保证 window 将处于活动状态并可用于处理输入事件。您需要一些方法在 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: Swing 是单线程的,不是线程安全的。永远不要从事件调度线程
的上下文之外更新UI因为 KeyListener
太……烦人了,更好的解决方案可能是使用 Key Bindings API,这将使您更好地控制应该生成关键事件的焦点级别.
也许更像...
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);
}
}
}
}