我正在使用java jinput
库从joypad读取数据,我无法重新加载Controllers
,我用它来加载它们:
public Controller[] findStickControllers() {
ControllerEnvironment ce =
ControllerEnvironment.getDefaultEnvironment();
Controller[] cs = ce.getControllers();
System.out.println(cs.length); //test
ArrayList<Controller> sel = new ArrayList<>();
for (Controller c: cs) {
if(c.getType() == Type.STICK) {
sel.add(c);
}
}
return sel.toArray(new Controller[]{});
}
这样可以正常工作,但是如果我断开控制器,调用它会再次找到它,反之亦然(在第一次检查后连接它根本就找不到它)。
我试图在第一次查找前进行睡眠,结果如下:
第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天等时间内重新加载控制器?
答案 0 :(得分:7)
我遇到了同样的问题。原因是每个DefaultControllerEnvironment对象只发生一次实际的硬件扫描。由于唯一可访问的实例化是单例,因此它永远不会进行另一次扫描。
强制硬件扫描的一种简单方法是创建一个新对象,但类和构造函数都不是公共的。但是,您可以通过反射调用构造函数来解决此限制。
重新扫描
private static ControllerEnvironment createDefaultEnvironment() throws ReflectiveOperationException {
// Find constructor (class is package private, so we can't access it directly)
Constructor<ControllerEnvironment> constructor = (Constructor<ControllerEnvironment>)
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<Object>() {
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;
}
});
}
答案 1 :(得分:2)
如果您使用接受的答案,您可能需要考虑在设置新答案之前杀死先前环境产生的线程,否则将无法清除它。您可以通过调用以下内容来执行此操作:
final Set<Thread> 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();
}
}
}
答案 2 :(得分:1)
警告是因为我最后一次更新代码窗口7甚至没有IIRC,我会更新它。
控制器重新加载是一项已被请求多次的功能,但没有人认为重要的是花费任何时间来实现它。如果您提交补丁,我会看看并提交有关提交。直到有人发现重要的是花时间写它,这只是一个缺失的功能。
答案 3 :(得分:1)
之前我遇到过同样的问题。 我添加了重新扫描功能(仅适用于Windows后端),并在Java游戏论坛上发布补丁,但似乎没有人愿意将其集成。
因此,如果您需要,请从此处应用我的补丁:http://www.java-gaming.org/topics/rescan-controllers/24782/msg/224604/view.html#msg224604