【问题标题】:Java Jinput: rescan / reload controllersJava Jinput:重新扫描/重新加载控制器
【发布时间】:2013-06-29 02:50:27
【问题描述】:

我正在使用 java jinput 库从手柄读取数据,但我无法重新加载 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[]{});
}

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

我尝试在第一次查找之前先休眠,结果如下:

  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 上遇到了同样的问题。我也用鼠标尝试过,结果相同。

我怎样才能在第二次、第三次等时间重新加载控制器?

【问题讨论】:

标签: java controller reload jinput


【解决方案1】:

如果您使用已接受的答案,您可能需要考虑在设置新环境之前终止由先前环境生成的线程,因为否则它不会被清理。您可以通过以下方式调用:

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】:

    我遇到了同样的问题。原因是对于每个 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;
            }
        });
    
    }
    

    【讨论】:

    • 我在 main 方法所在的地方添加了这个方法(createDefaultEnvironment),但我无法让它工作。如果您能添加更多详细信息,我将非常感谢。
    • 我添加了一个示例。本质上,您需要用 createDefaultEnvironment() 替换对 ControllerEnvironment.getDefaultEnvironment() 的调用
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      警告是因为我上次更新代码 windows 7 甚至没有出 IIRC,我会更新它。

      控制器重新加载是一项已被多次请求的功能,但没有人认为它足够重要以花时间实现它。如果您提交补丁,我会查看并了解如何提交它。直到有人发现它足够重要以至于花时间编写它,它只是一个缺失的功能。

      【讨论】:

      • 没有人认为花时间实施它足够重要我完全感到惊讶。然而,它看起来是真的。每次我想重新扫描控制器时,我已经通过启动新的Process 来避免这个问题,但这真的很糟糕。
      猜你喜欢
      • 2014-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多