如何检测按键

时间:2013-11-28 15:57:07

标签: java keyboard key user-input

我正在使用java并尝试编写一个简单的sudo鼠标记录器,它将在按下空格键时存储鼠标位置。我需要检测的唯一键是空格键(虽然如果另一个键更容易,那将起作用)。

我需要用java编写整个鼠标记录器,但是如果按键的功能是另一种语言则可以。我将在Windows 7中运行它。

做最简单的方法是什么?我发现的所有方法都需要至少20行代码。这没关系,除了我不明白如何实现它们。我在下面有一个示例来源:

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

2 个答案:

答案 0 :(得分:1)

由于你没有发表我的评论,你的问题再次不清楚了:

  

我觉得你可能想要一个系统范围的键盘记录器,它只响应一次按键,而且不需要GUI。如果是这样,那么最好的解决方案是不使用Java来创建应用程序,而是使用可以更接近操作系统的工具。如果这是一个Windows项目,我会想到AutoIt。请更好地定义您的需求。

这迫使我们猜测问题及其解决方案。


如果您有兴趣创建一个Swing GUI,让它成为焦点,并让它听取关键事件,那么解决方案就是这样做:

  • 创建Swing GUI并显示它,在应用程序运行时将其保留为活动的窗口化应用程序。
  • 使用键绑定让它听空格键按
  • 然后在按下空格键时记录鼠标位置。
  • 如上所述,这在5行代码中无法实现,所以将这个想法放在一边。

另一方面,如果您希望没有GUI,而是在任何和所有应用程序运行时都要听热键按下,那么

  • 使用的可能平台将是至关重要的,因为您的解决方案将需要特定于操作系统的代码,因为创建热键意味着必须创建键盘处理程序例程(通常在C中),并为每个平台执行此操作,然后将其链接到使用JNI或JNA到Java。
  • 或者如前所述,另一种方法是将Java程序与OS特定的实用程序或脚本(如AutoIt)链接。

如果您需要更具体的帮助,请澄清您的问题。


修改
你说:

  

感谢您的回答,但正如我上面所描述的那样:“改变语言是不可能的,尽管看起来似乎更容易。”并且“我不想要一个gui,如果我可以避免它”

然后我的第二个答案就是你要找的东西。您对C / C ++,JNI或JNA的熟练程度如何,以及您对操作系统库的了解有多好?如果你想要一个只有Java的解决方案,我会认为你的要求远远高于初学者或中级Java,进入高级领域 - 或者至少超出我的能力,尽管我确信我可以提出一些解决方案几天到一两周的学习。

...或者考虑摆脱“更改语言”的要求,而是至少允许将Java与脚本实用程序(如AutoIt)结合在一起。这可以允许在更短的时间内创建解决方案,至少对我而言。但是,这些限制将是平台特定的解决方案。这一切背后的目的是什么?这可能是伪装的XY问题吗?


修改2

我决定尝试用一个与Java相连的小型AutoIt实用程序来解决这个问题,这就是我想出来的。

我的AutoIt程序名为CaptureHotKey.au3,在使用前编译为exe:

$key = $CmdLine[1]

HotKeySet($key, "hotKeyFunction")

While 1
    Sleep(100)
WEnd

Func hotKeyFunction()
    ConsoleWrite(@CRLF)
EndFunc

没有太大的意义。它只是从第一个命令行参数设置一个热键,提供一个无限循环,以便它继续运行,并且一个非常简单的热键功能,只发送一个回车/换行给它控制台(将是标准输出)。


然后是一个Java类来帮助与此进行交互。它使用SwingPropertyLanguageSupport来允许添加在Swing线程上响应的PropertyChangeListener(如果我想在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;
      }
   }
}

最后用Java类来测试这个设置:;

这会在上面的类中添加一个PropertyChangeListener,以便在按下热键时通知它:

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

}

答案 1 :(得分:-1)

您应该使用KeyListener:http://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html 它适用于Swing