Java Jinput:重新扫描/重新加载控制器

我正在使用java jinput库从jinput读取数据,我无法重新加载Controllers ,我使用它来加载它们:

 public Controller[] findStickControllers() { ControllerEnvironment ce = ControllerEnvironment.getDefaultEnvironment(); Controller[] cs = ce.getControllers(); System.out.println(cs.length); //test ArrayList sel = new ArrayList(); for (Controller c: cs) { if(c.getType() == Type.STICK) { sel.add(c); } } return sel.toArray(new Controller[]{}); } 

这工作正常,但如果我断开我的控制器,调用它将再次找到它,反之亦然(在第一次检查后连接它将根本找不到它)。

我试图在第一次查找前放入睡眠,结果如下:

  1. 第一次调用此方法时(而非程序启动时)会对控制器进行实际扫描
  2. 再次调用时,它总是返回与第一次返回的控制器相同的控制器。
  3. 第一次打电话也会写下警告
  4. 即使控制器连接(并且工作),然后断开连接(它仍然会找到它)并重新连接,它将无法工作

第3点的警告:(列表格式不正确)

 WARNING: Found unknown Windows version: Windows 8 Attempting to use default windows plug-in. Loading: net.java.games.input.DirectAndRawInputEnvironmentPlugin 

我正在使用Win 8,并且在Win 7上遇到了同样的问题。我也用鼠标试过这个,结果相同。

如何在第2次,第3次等时间内重新加载控制器?

我遇到了同样的问题。 原因是每个DefaultControllerEnvironment对象只发生一次实际硬件扫描。 由于唯一可访问的实例化是单例,因此它永远不会进行另一次扫描。

强制硬件扫描的一种简单方法是创建一个新对象,但类和构造函数都不是公共的。 但是,您可以通过reflection调用构造函数来解决此限制。

重新扫描

 private static ControllerEnvironment createDefaultEnvironment() throws ReflectiveOperationException { // Find constructor (class is package private, so we can't access it directly) Constructor constructor = (Constructor) Class.forName("net.java.games.input.DefaultControllerEnvironment").getDeclaredConstructors()[0]; // Constructor is package private, so we have to deactivate access control checks constructor.setAccessible(true); // Create object with default constructor return constructor.newInstance(); } 

用法

 // Be aware that creating a new environment is fairly expensive Controller[] controllers = createDefaultEnvironment().getControllers(); 

删除Windows 8警告

 /** * Fix windows 8 warnings by defining a working plugin */ static { AccessController.doPrivileged(new PrivilegedAction() { public Object run() { String os = System.getProperty("os.name", "").trim(); if (os.startsWith("Windows 8")) { // 8, 8.1 etc. // disable default plugin lookup System.setProperty("jinput.useDefaultPlugin", "false"); // set to same as windows 7 (tested for windows 8 and 8.1) System.setProperty("net.java.games.input.plugins", "net.java.games.input.DirectAndRawInputEnvironmentPlugin"); } return null; } }); } 

如果您使用接受的答案,您可能需要考虑在设置新答案之前杀死先前环境产生的线程,否则将无法清除它。 您可以通过调用以下内容来执行此操作:

 final Set threadSet = Thread.getAllStackTraces().keySet(); for (final Thread thread : threadSet) { final String name = thread.getClass().getName(); if (name.equals("net.java.games.input.RawInputEventQueue$QueueThread")) { thread.interrupt(); try { thread.join(); } catch (final InterruptedException e) { thread.interrupt(); } } } 

警告是因为我最后一次更新代码窗口7甚至没有IIRC,我会更新它。

控制器重新加载是一项已被请求多次的function,但没有人认为重要的是花费任何时间来实现它。 如果您提交补丁,我会看看并提交有关提交。 直到有人发现重要的是花时间写它,这只是一个缺失的function。

我之前遇到过同样的问题。 我添加重新扫描function(仅适用于Windows后端)并在Java游戏论坛上发布补丁,但似乎没有人愿意将其集成。

因此,如果您需要,请从此处应用我的补丁: http : //www.java-gaming.org/topics/rescan-controllers/24782/msg/224604/view.html#msg224604