[Nifty] DropDown getSelectedIndex is returning null?

What I’m trying to do is create a dropdown that has a list of resolutions to choose from and based on the getSelectedIndex() it changes to that resolution. However, even if I have something selected in the getSelectedIndex() I’m getting a nullpointer.



Here is the code.(I realize there are better ways to have set a ‘set resolution’ option, yeah.)

[java]public void changeSettings(){

int index = resolution.getSelectedIndex();

switch(index){

case 0: width = 640;

height = 480;

…[/java]



When ever I click ‘Apply’ (Which invokes the above code, and it works without the resolution.getSelectedIndex() line when I manually set the index variable) it gives me

(line 97 is the ’ int index = resolution.getSelectedIndex();’ )



[xml]SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]

java.lang.NullPointerException

at gamerScreen.OptionsScreen.changeSettings(OptionsScreen.java:97)[/xml]





So what am I doing wrong here? Am I miss understanding what getSelectedIndex does?

Well, if you get the NPE on that line, the only thing that can be null is the resolution variable.

Are you sure it is initialized at that point?

Yes, I have a resolution selected from the drop down menu when I hit apply and run that part of the code.

Perhaps you could post some more code so we can see the context and program flow?

Alright.





[java]



OptionsScreen.java

package gamerScreen;





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.system.AppSettings;

import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.builder.ScreenBuilder;

import de.lessvoid.nifty.controls.DropDown;

import de.lessvoid.nifty.elements.Element;

import de.lessvoid.nifty.screen.Screen;

import de.lessvoid.nifty.screen.ScreenController;

import java.awt.image.BufferedImage;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Comparator;

import java.util.List;

import java.util.prefs.BackingStoreException;

import org.lwjgl.opengl.Display;

import org.lwjgl.opengl.DisplayMode;



public class OptionsScreen extends AbstractAppState implements ScreenController {



private Nifty nifty;

private GuiGameBase base = GuiGameBase.returnInstance();

private Screen screen;

private SimpleApplication app;

private AppSettings settings = new AppSettings(true);

private DropDown resolution;

private DropDown colordepth;

private boolean updateScreen;

private String mainScreen;

private int width, height, depth, freq;

private boolean fullscreen;



/** Nifty GUI ScreenControl methods /



public void bind(Nifty nifty, Screen screen) {

this.nifty = nifty;

this.screen = screen;



DropDown resolution = screen.findNiftyControl("resolution", DropDown.class);

resolution.addItem("640 x 480");

resolution.addItem("800 x 600");

resolution.addItem("1024 x 768");

resolution.addItem("1152 x 864");

resolution.addItem("1280 x 720");



resolution.selectItemByIndex(0);



DropDown colordepth = screen.findNiftyControl("colordepth", DropDown.class);

colordepth.addItem("16 bit");

colordepth.addItem("32 bit");





}



public void onStartScreen() { }



public void onEndScreen() { }



public void startGame(){



}



public void changeScreen(String nextScreen){

nifty.gotoScreen(nextScreen);



}



/
* jME3 AppState methods /



@Override

public void initialize(AppStateManager stateManager, Application app) {

super.initialize(stateManager, app);

this.app=(SimpleApplication)app;



}



public void applyCon(String main){

updateScreen = true;

mainScreen = main;

}



public void applySettings(){

changeSettings();

app.restart();

updateScreen = false;

nifty.gotoScreen(mainScreen);



}



public void changeSettings(){

int index = resolution.getSelectedIndex();

switch(index){

case 0: width = 640;

height = 480;

case 1: width = 800;

height = 600;

case 2: width = 1024;

height = 768;

case 3: width = 1152;

height = 864;

case 4: width = 1280;

height = 720;

default: ;

}

switch(2){

case 0: depth = 16;

case 1: depth = 32;

default: ;

}







settings.setSettingsDialogImage("Interface/Logo.png");

freq = settings.getFrequency();

fullscreen = settings.isFullscreen();





settings.setFullscreen(fullscreen);

settings.setResolution(width, height);

settings.setBitsPerPixel(depth);

settings.setFrameRate(freq);



try { settings.save("gamerScreen"); }

catch (BackingStoreException ex) { /
* could not save settings / }



app.setSettings(settings);



}





@Override

public void update(float tpf) {

/
* jME update loop! */

if(updateScreen == true){

applySettings();

}

}



}[/java]



OptionsScreen.xml



[xml]<?xml version="1.0" encoding="UTF-8"?>

<nifty xmlns="http://nifty-gui.sourceforge.net/nifty-1.3.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nifty-gui.sourceforge.net/nifty-1.3.xsd http://nifty-gui.sourceforge.net/nifty-1.3.xsd">

<!-- +++++++++++++++++++++++++++++++++++++++ -->

<!-- Options screen -->

<!-- +++++++++++++++++++++++++++++++++++++++ -->



<useControls filename="nifty-default-controls.xml" />

<useStyles filename="Interface/Styles/customStyles.xml" />

<registerSound id="myclick" filename="Interface/hover.wav" />



<screen id="startOptions" controller="gamerScreen.OptionsScreen" childLayout="center">

<layer id="background" childLayout="center">

<image filename="Interface/backgroundTitle.png" imageMode="normal" ></image>

</layer>

<layer id="foreground" childLayout="horizontal" >

<panel id="text" width="50%" height="100%" childLayout="vertical" >

<text text="Resolution . . . . . . . . . . . . . . . " font="Interface/Fonts/Default.fnt" width="100%" height="15%" />

<text text="Color Depth . . . . . . . . . . . . . . ." font="Interface/Fonts/Default.fnt" width="100%" height="15%" />

<text text="Fullscreen . . . . . . . . . . . . . . ." font="Interface/Fonts/Default.fnt" width="100%" height="15%" />

<panel width="100%" height="45%"></panel>

<panel width="100%" height="10%" childLayout="center">

<control name="button" label="Main Menu" id="MM" align="center" valign="center"

visibleToMouse="true" >

<interact onClick="changeScreen(start)"/>

<effect>

<onHover name="playSound" sound="myclick"/>

<onHover name="pulsate" scaleFactor="0.008" startColor="#f600" endColor="#ffff" post="true"/>

</effect>

</control>

</panel>

</panel>

<panel id="options" width="50%" height="100%" childLayout="vertical">

<panel width="100%" height="4%"></panel>

<control name="dropDown" id="resolution" width="100%" height="5%" align="center" valign="center"

visivleToMouse="true">

</control>

<panel width="100%" height="10%"></panel>

<control name="dropDown" id="colordepth" width="100%" height="5%" align="center" valign="center"

visivleToMouse="true">

</control>

<control name="button" label="Apply" id="apply" align="center" valign="center"

visibleToMouse="true" >

<interact onClick="applyCon(start)"/>

<effect>

<onHover name="playSound" sound="myclick"/>

<onHover name="pulsate" scaleFactor="0.008" startColor="#f600" endColor="#ffff" post="true"/>

</effect>

</control>

</panel>





</layer>

</screen>

</nifty>

[/xml]

Ok, that looks alright.

The interesting part is then where you call your applyCon method, specifically how you get your instance of the OptionsScreen class.

Do you use nifty.getCurrentScreen().getScreenController() or do you perhaps create a new instance (rather than using the instance Nifty created)?

Sorry, but I’m not quite following you. The only place I call my applyCon method is in my OptionsScreen.xml when you click the ‘Apply’ button.

(Side question, if you have time. When making a HUD with nifty, I enable the flyCam but how do I get the mouse away form nifty and back to fly cam?)

Ah, I see.

But the call to the applySettings method is called as part of the jme update loop, on some instance of the class added as an AppState.

How do you get the instance of OptionsScreen that you attach to the app state manager?

I suspect the problem lies there.



As for the mouse problem, I’m afraid I don’t quite know.

Man, you have created 2 “resolution” variables, a local, and a private instance. Your private instance is null, you’ve only instanced the local variable.

The solution is way easier than it looks, just replace the following line:



[java]

DropDown resolution = screen.findNiftyControl(“resolution”, DropDown.class);

[/java]



with that:



[java]

resolution = screen.findNiftyControl(“resolution”, DropDown.class);

[/java]

Hmm, ok.



Edit: Yeah, that fixed the null pointer error. I would have never thought of that. Now I just have to figure out why it isn’t changing the resolution now.

Before, I entered the number directly for case(index) and it would change the resolution to the index I chose. However, even if I enter it manually, it’s no longer changing the resolution though it is restarting the screen.

yeah, I’ve already had the same problem before. If you call app.restart() it will change the resolution, but it doesn’t work properly with nifty. My workaround was warning the user to restart the application.

Even if I restart the application manually it still doesn’t change the settings. I’ve backtracked to how I had it before when it did change the resolution and did work, but that doesn’t work either. Maybe the first time it worked it was a fluke or something.

And restarting the application does work?

EDIT: When I mean “restarting the application” I mean exit the application and opening it again.

Yes, that doesn’t work. I close it and restart it and it’s not actually resetting the settings.

Well, so you are doing something wrong, maybe your option screen doesn’t reach the line 127. Do a debug.