Cant interact with the GUI because Nifty is null!

Hi guys!

So, I implemented today GUI interaction to be able to close and start the game. However, whenever the methods are called, my nifty object is null for some reason.

The Nifty object I get from the bind() method is the same as my nifty object

Here is my AppState that implements the ScreenController:

public void initialize() {
    [...]

    // Starts and loads the GUI
    this.niftyJME = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);
    this.nifty = this.niftyJME.getNifty();
    this.nifty.fromXml("Interface/gui.xml", "start", this);
    this.nifty.registerScreenController(this);
    this.app.getGuiViewPort().addProcessor(niftyJME);

    
    // Continues to initialize
    super.initialize(stateManager, app);
}

@Override
public void update(float tpf) {
    
}

@Override
public void bind(Nifty nifty, Screen screen) {
    
}

@Override
public void onStartScreen() {
    
}

@Override
public void onEndScreen() {
    
}

// Nifty's methods
public void startGame() {
    nifty.removeScreen("start");
}

public void endGame() {
    cleanup();
}

My XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nifty xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://nifty-gui.lessvoid.com/nifty-gui" xsi:schemaLocation="https://raw.githubusercontent.com/void256/nifty-gui/1.4/nifty-core/src/main/resources/nifty.xsd https://raw.githubusercontent.com/void256/nifty-gui/1.4/nifty-core/src/main/resources/nifty.xsd">
    <useControls filename="nifty-default-controls.xml"/>
    <useStyles filename="nifty-default-styles.xml"/>
    <screen id="start" controller="guiControllers.MenuController">
        <layer id="gui" childLayout="vertical" backgroundColor="#000a">
            <panel id="title" childLayout="center" width="100%" style="" height="20%">
                <control name="label" id="titleLabel" textVAlign="center" width="100%" style="" text="Strategy" font="Interface/Fonts/Title.fnt" height="100%"/>
            </panel>
            <panel id="play" childLayout="center" width="100%" style="" height="50%">
                <control name="button" id="playButton" childLayout="center" style="nifty-button" valign="center" label="Jogar" visibleToMouse="true">
                    <interact onClick="startGame()" />
                </control>
            </panel>
            <panel id="others" childLayout="horizontal" width="100%" style="" height="20%">
                <panel id="emptySpace1" childLayout="center" width="20%" style="" height="100%"/>
                <panel id="help" childLayout="center" width="20%" style="" height="100%">
                    <control name="button" id="helpButton" childLayout="center" label="Ajuda"/>
                </panel>
                <panel id="options" childLayout="center" width="20%" style="" height="100%">
            </panel>
            <panel id="exit" childLayout="center" width="20%" style="" height="100%">
                <control name="button" id="exitButton" childLayout="center" valign="center" label="Sair">
                    <interact onClick="endGame()"/>
                </control>
            </panel>
            <panel id="emptySpace2" childLayout="center" width="20%" style="" height="100%"/>
        </panel>
        <panel id="copyright" childLayout="center" width="100%" style="" height="10%">
            <control name="label" id="copyrightLabel" width="100%" style="" text="Copyright 2015 GODE. GODE provides software only. Use of GODE's software is subject to our Terms of Services and Privacy Policy." wrap="true" font="aurulent-sans-16.fnt" height="100%"/>
        </panel>
    </layer>
</screen>

I looked in the forum for similar problems, but none of those helped me.

Thanks,
Ev1lbl0w

I had a problem like this, it was due to calling registerScreenController after calling fromXML. Try calling the registerScreenController before calling fromXML.

What methods?

Hard to comment on them when we can’t see that.

The “startGame” and “endGame” methods are the ones he’s calling in this example. In this case, I would try what neumann347 said. You are creating a new copy of the screen controller and you aren’t capturing the “nifty” object in the bind method so it is null.

Thanks for the replys.

@neumann347 and @glh3586 I tried registereing the screen before loading the XML but I still get the same problem. I also tried to catch the bind() Nifty object and pass it to my object. Still fails.

@pspeed sorry for not being clear. The two methods I am calling are, as glh3586 said, startGame() and endGame().

Post your full code then with the changes we suggested and I’ll take a closer look.

Well, I don’t see where ScreenController is mentioned in your XML… only something called MenuController… and I guess we don’t know what that code is. Either way, I guess it has not been registered with nifty and so nifty will create an instance for you using the no-arg constructor.

Oh, sorry about that. I modified the code of that line to make a test, and forgot to take in out when sending the thread.

This is the tag I’m using:

<screen id="start" controller="appstates.MenuAppState">

And since my MenuAppState is small, I decided to put it here:

package appstates;

import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioRenderer;
import com.jme3.input.InputManager;
import com.jme3.niftygui.NiftyJmeDisplay;
import com.jme3.renderer.ViewPort;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;

public class MenuAppState extends AbstractAppState implements ScreenController {
    
    // Variables
    // Application
    private SimpleApplication app;
    private AppStateManager stateManager;
    // App's variables
    private AssetManager assetManager;
    private InputManager inputManager;
    private AudioRenderer audioRenderer;
    private ViewPort guiViewPort;
    // GUI
    private NiftyJmeDisplay niftyJME;
    private Nifty nifty;
    
    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        this.app = (SimpleApplication)app;
        this.stateManager = stateManager;
        this.assetManager = this.app.getAssetManager();
        this.inputManager = this.app.getInputManager();
        this.audioRenderer = this.app.getAudioRenderer();
        this.guiViewPort = this.app.getGuiViewPort();
        
        // Starts and loads the GUI
        this.niftyJME = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);
        this.nifty = this.niftyJME.getNifty();
        this.nifty.registerScreenController(this);
        this.nifty.fromXml("Interface/gui.xml", "start", this);
        //this.nifty.fromXml("Interface/gui.xml", "start", new MenuController());
        this.app.getGuiViewPort().addProcessor(niftyJME);
        
        // Enables the mouse and disables the flyCam
        inputManager.setCursorVisible(true);
        this.app.getFlyByCamera().setEnabled(false);
        
        // Continues to initialize
        super.initialize(stateManager, app);
    }
    
    @Override
    public void update(float tpf) {
        
    }
    
    @Override
    public void bind(Nifty nifty, Screen screen) {
        
    }
    
    @Override
    public void onStartScreen() {
        
    }
    
    @Override
    public void onEndScreen() {
        
    }
    
    // Nifty's methods
    public void startGame() {
        nifty.removeScreen("start");
    }
    
    public void endGame() {
        cleanup();
    }
    
    @Override
    public void cleanup() {
    

//nifty.removeScreen("start");
    
    // Continues to clean up
    super.cleanup();
}
}

And you actually attache this app state?

Anyway, I will let others help you as I swore I’d stop trying to help folks with nifty magic 5 years ago when I dropped it. Good luck, though… this is well trod territory, this issue.

Yes, I attach the appstate. Otherwise, the GUI wouldn’t appear.

Some users have been known to call initialize() manually. It’s very difficult for folks to assume things about code that they cannot see… which is why test cases are usually requested.

Okay… so to start with… I don’t think you tried to run this because pasting this all into a new project resulted in it not even running. The screen controller you reference in your gui.xml doesn’t reference the screen controller app state you posted. You referenced a completely different package structure. Look at the debug output as well. Once I fixed the gui.xml package name to match “appstates.MenuAppState” which is what you posted it ran fine and I didn’t get a null pointer error when I clicked start game. Your package structure looks a little weird for a java project.

Yeah, it was kinda my bad. As I said above, I was making a test, and when I pasted the code in the thread, I forgot to change the ScreenController reference.

This is tag I’m currently using:

<screen id="start" controller="appstates.MenuAppState">

So, if you got it working, I guess I’m doing something wrogn in the code then.

The only place I use that AppState is in my Main class:

MenuAppState menuAppState = new MenuAppState();
stateManager.attach(menuAppState);

That is all I had in my main class. Which version of JME are you using?

The latest in the Download section. Alpha 1

Okay that’s not it then since I’m running 3.1 too. Why are you calling remove screen? Normally you would just call goto screen to switch.

I just want to make the screen disappear for now. Later I’ll switch to a “hud” screen.

So, I decided to to a test project like you did. I copied the AppState, the XML and the fonts. I created a simple app that literally only has the methods to attach the appState. I still crash with nulls.

You should probably show the code. Always always always shot the code. And when in doubt, show the code.

No one in my entire time of being on this forum has ever complained about having too much information in a post… but DAILY we complain about not enough.

2 Likes

Well removing it doesn’t just make it disappear but removes it from nifty. It’s possible you are causing a timing bug. Without seeing your stack trace and code for your test project I couldn’t say more.

Edit:
I just ran it again and got a null point error but not in the section you specified. Removing the screen was causing a null pointer error in the binding between jme and nifty.