问题
I am using java and trying to write a simple sudo mouse recorder that will store the mouse position when the space key is pressed. The only key I need to detect is the space key (Although if another key is easier, that will work).
I need the whole mouse recorder to be written in java, but it is OK if the function for the keypress is in another language. And I will be runing this in Windows 7.
What is the simplest way to do what has been described? All of the methods I have found require at minimum 20 lines of code. This is OK, except I don't understand how to implement them. I have an example source below:
import java.awt.MouseInfo;
import javax.swing.JOptionPane;
public class MouseRecorder {
public static void main (String[] args)
{
int slot = 0;
int xLoc[10];
int yLoc[10];
while (slot <= 10)
{
if (keyPressed(KEY_SPACE)) //<<<<This obviously won't work, but I'm looking for the simplest way to code this
{
xLoc[slot] = MouseInfo.getPointerInfo().getLocation().x;
yLoc[slot] = MouseInfo.getPointerInfo().getLocation().y;
slot++;
}
}
//The mouse information can now be utilized
}
}
回答1:
Again your question is not clear since you have not addressed my comment:
It smells like to me that you might want a system-wide key logger that only responds to one key press, and that doesn't need a GUI. If this is so, then your best solution is to not use Java to create your application but to use a tool that can get closer to the OS. AutoIt comes to mind if this is for a Windows project. Please define your needs better.
and this forces us to guess at the problem and its solution.
If you are interested in creating a Swing GUI, having it take focus, and have it listen to key events, then the solution is to do this:
- Create your Swing GUI and display it, leaving it as the active windowed application while your application is running.
- Using Key Bindings have it listen for space bar presses
- And then log the mouse location when the space bar is pressed.
- As noted, this will not be achievable in 5 lines of code, so put that idea to the side.
If on the other hand your desire is to not have a GUI but rather listen for hot-key presses while any and all applications are running, then
- The possible platforms used will be critical since your solution will require OS-specific code since creating a hot-key means having to create a keyboard handler routine, often in C, and doing this for each platform, and then linking it in to Java using JNI or JNA.
- Or as noted another way is to link your Java program with an OS specific utility program or script such as AutoIt.
If you need more specific help, then please clarify your question.
Edit
You state:
Thank you for the answer, but as I have described above: "Changing languages is out of the question although it seems like that might be easier." and "I dont want a gui, if I can avoid it"
Then my second answer is what you're looking for. How adept are you at C/C++, JNI or JNA, and how good is your knowledge of operating system libraries? If you want a Java only solution, I would consider your requirements far above beginner or intermediate Java and into the realm of advanced -- or at least beyond my abilities at the moment, although I am sure that I could come up with some solutions after several days to a week or two of study.
... or consider getting rid of your "changing languages" requirement and instead allow at least meshing Java together with a scripting utility, like AutoIt. That could allow creation of solutions in a shorter period of time, at least for me. A limitation though is that these would be platform specific solutions. What is your purpose behind all of this? Could this be an XY problem in disguise?
Edit 2
I decided to try to solve this with a small AutoIt utility that I meshed with Java, and this is what I came up with.
My AutoIt program is called CaptureHotKey.au3, and it is compiled to an exe before use:
$key = $CmdLine[1]
HotKeySet($key, "hotKeyFunction")
While 1
Sleep(100)
WEnd
Func hotKeyFunction()
ConsoleWrite(@CRLF)
EndFunc
There's not much to it. All it does is set a hot-key from the first command line parameter, provides an endless while loop so that it will continue to run, and a hotkey function that is quite simple and only sends a carriage-return/line-feed to the console (which will be the standard output).
Then a Java class to help interact with this. It uses SwingPropertyLanguageSupport to allow addition of PropertyChangeListeners that respond on the Swing thread (in case I want to use this with a GUI).
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import javax.swing.event.SwingPropertyChangeSupport;
public class CaptureHotKey implements Runnable {
public static final String HOT_KEY = "hot key";
private String hotKey;
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
this);
private Scanner scanner;
private CaptureHotKeyFromAutoIt capture;
public CaptureHotKey(final String hotKey) throws IOException {
this.hotKey = hotKey;
capture = new CaptureHotKeyFromAutoIt(hotKey);
scanner = new Scanner(capture.getReadable());
}
public void startCapturing() {
new Thread(this).start();
}
public void exit() {
if (capture != null) {
capture.exit();
}
if (scanner != null) {
scanner.close();
}
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public String getHotKey() {
return hotKey;
}
@Override
public void run() {
while (scanner != null && scanner.hasNextLine()) {
scanner.nextLine();
pcSupport.firePropertyChange(HOT_KEY, true, false);
}
}
private static class CaptureHotKeyFromAutoIt {
public static final String AUTO_IT_APP_PATH = "CaptureHotKey.exe";
private Process process = null;
private ProcessBuilder pb;
public CaptureHotKeyFromAutoIt(String hotKey) throws IOException {
List<String> cmdList = new ArrayList<>();
cmdList.add(AUTO_IT_APP_PATH);
cmdList.add(hotKey);
pb = new ProcessBuilder(cmdList);
pb.redirectErrorStream(true);
process = pb.start();
}
public void exit() {
if (process != null) {
process.destroy();
}
}
public Readable getReadable() {
if (process != null) {
return new InputStreamReader(process.getInputStream());
}
return null;
}
}
}
Finally a Java class to test this set up:;
This adds a PropertyChangeListener to the class above to allow it to be notified if the hot-key is pressed:
import java.awt.MouseInfo;
import java.awt.PointerInfo;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Scanner;
public class CaptureHotKeyTest {
public static final String CTRL_R = "^r"; // "{SPACE}" works for spacebar
private static final String EXIT = "exit";
private CaptureHotKey capture;
public CaptureHotKeyTest() {
try {
capture = new CaptureHotKey(CTRL_R);
capture.addPropertyChangeListener(new HotKeyPropertyChngListener());
capture.startCapturing();
Scanner scan = new Scanner(System.in);
System.out.println("Press control-r to get mouse position.");
System.out.println("Type \"exit\" to exit program");
while (scan.hasNextLine()) {
String line = scan.nextLine();
if (line.equalsIgnoreCase(EXIT)) {
scan.close();
capture.exit();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class HotKeyPropertyChngListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(CaptureHotKey.HOT_KEY)) {
System.out.println("hot key pressed");
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
System.out.println("Mouse: " + pointerInfo.getLocation());
}
}
}
public static void main(String[] args) {
new CaptureHotKeyTest();
}
}
回答2:
You should use KeyListener: http://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html It works fine with Swing
来源:https://stackoverflow.com/questions/20270353/how-to-detect-keypress