Nifty-GUI 1.4消耗键盘事件(LWJGL 2.9.2)

时间:2015-01-20 14:34:04

标签: java input lwjgl nifty-gui

我在Nifty-GUI的事件处理方面遇到了很多问题,并在互联网上寻找解决方案,但没有真正发现任何问题(我想避免实现自己的输入系统)。问题是,一旦我开始对我的应用程序使用漂亮,LWJGL似乎不再获得任何键盘输入。我已经尝试了一些像nifty.setIgnoreKeyboardEvents(true)这样的东西,但它没有改变任何东西。我知道我可能做错了什么,但我希望有人可以帮助我。

以下是相关的代码摘录:

UI类负责设置漂亮。它在另一个名为Graphics的类中实例化(实现Runnable,这应该很重要),但只有在LWJGL和OpenGL初始化之后才会实现。

public class UI {

    private Nifty nifty;

    public UI() {
        initUI();
    }

    private void initUI() {
        LwjglInputSystem inputSystem = initInput();
        nifty = initNifty(inputSystem);
        nifty.setIgnoreKeyboardEvents(true);
        nifty.fromXml("resources/ClientStartScreen.xml", "start", 
                new ClientStartController());
    }

    private LwjglInputSystem initInput() {
        try {
            LwjglInputSystem inputSystem = new LwjglInputSystem();
            inputSystem.startup();
            inputSystem.niftyHasKeyboardFocus = false;
            inputSystem.niftyTakesKeyboardFocusOnClick = false;
            return inputSystem;
        } catch(Exception e) {
            System.out.println("[ERROR:] Input System could not be"
                    + "initialised.");
            System.out.println(e.getMessage());
            return null;
        }
    }

    private Nifty initNifty(LwjglInputSystem inputSystem) {
        try {
            return new Nifty(new BatchRenderDevice(
                    LwjglBatchRenderBackendCoreProfileFactory.create()),
                    new NullSoundDevice(), inputSystem, 
                    new AccurateTimeProvider());
        } catch(Exception e) {
            System.out.println("[ERROR:] Nifty could not be initialised.");
            System.out.println(e.getMessage());
            return null;
        }
    }

    public Nifty getNifty() {
        return nifty;
    }
}

我使用的屏幕是最小的例子,所以这里应该没有问题:

<?xml version="1.0" encoding="UTF-8"?>
<nifty xmlns="http://nifty-gui.lessvoid.com/nifty-gui">
    <useStyles filename="nifty-default-styles.xml" />
    <useControls filename="nifty-default-controls.xml" />

    <screen id="start"
            controller="htw.gt3.trappers.client.screens.ClientStartController">
        <layer childLayout="center">
            <text id="hellouser" font="aurulent-sans-16.fnt" color="#ffff" 
                  text="Hello user!" />
        </layer>
    </screen>

</nifty>

控制器没有做任何事情,只有空的覆盖方法。

我正在使用一个单独的班级来处理输入。它是游戏主循环的一部分(它是Graphics类的一部分)。在循环中调用的相关方法如下所示:

public void checkInput() {
    while(Keyboard.next()) {
        if(!Keyboard.getEventKeyState()) {
            if(Keyboard.getEventKey() == Keyboard.KEY_UP) {

然而,游戏永远不会进入while循环,因为正如我所说,键盘没有收到任何事件,因为它们之前很可能已经消耗过了。请注意,当我不使用nifty时,我的代码可以正常工作 - 所以当我不在我的Graphics类中创建UI对象并且只使用黑屏时,我的输入工作正常。

主循环如下所示:

boolean niftyDone = false;
while(!Display.isCloseRequested() && !niftyDone) {
    controls.checkInput();
    Display.update();
    Display.sync(60);
    if(ui.getNifty().update()) {
        niftyDone = true;
    }            
    ui.getNifty().render(true);
}

我真的很依赖你的帮助 - 希望有人知道问题是什么。

1 个答案:

答案 0 :(得分:0)

只要Nifty处于活动状态 - 您调用nifty.update() - 它当前将从LWJGL读取键盘事件,这意味着它们将不再可用。这是在LwjglInputSystem中的processKeyboardEvents()方法中完成的......而且......目前你无能为力。

但是,如果设置nifty.setIgnoreKeyboardEvents(true)或者Nifty没有处理事件(!),那么Nifty仍然会从LWJGL读取它们但是它会在内部将它们存储在队列中,你可以读取和处理他们以后自己!

您可以调用方法hasNextKeyboardEvent()和nextKeyboardEvent()来读取事件。您可以在此处找到LwjglInputSystem类中的方法:https://github.com/void256/nifty-gui/blob/1.4/nifty-renderer-lwjgl/src/main/java/de/lessvoid/nifty/renderer/lwjgl/input/LwjglInputSystem.java#L88

这样你仍然可以处理Nifty没有处理的键盘事件:)

PS:当然,更普遍的问题是有人赢得了LWJGL的键盘事件。它既是你的游戏,也是Nifty赢得它们的 - 或者你需要自己将它们转发给Nifty ......或者它是Nifty读取事件然后它们不是使用常规的Keyboard.next()方法为您的游戏提供。

我们决定使用第二个选项,因为在很多情况下,人们只会使用GUI(菜单屏幕等)而不会同时激活游戏代码。因此,在这些情况下,它会为用户添加更多工作以手动转发事件,但使用当前的解决方案,它可以开箱即用而无需额外的工作。

但是对于你需要两者的情况,我认为上面的解决方案应该可以正常工作。