I am working on a game using JME3 and Nifty GUI. I have an outer class that has a Nifty
member variable. And the inner class should be able to access that variable regardless of access modifier. In the constructor I assign a new Nifty
object to it. However when I access that variable in the inner class I run into problems. I did a little debugging and found out it's because the inner class thinks the Nifty
member variable is null and I cant figure out why. Its not null in the outer class. Since this is a JME3 game I tried to have the inner class implement the AppState
interface but it still shows the Nifty
member variable as null. Here is the code:
public class MenuScreen extends SimpleApplication {
/** Used to configure Nifty GUI. */
private Nifty mNifty;
private NiftyJmeDisplay mNiftyDisplay;
private Element popup;
//*******************
// Overridden medhods
//*******************
/** This method is used to initialize everything needed to display the game screen. */
@Override
public void simpleInitApp() {
guiNode.detachAllChildren();
initNifty();
flyCam.setDragToRotate(true);
}
/**
* The game's main update loop.
*
* @param tpf Time Per Fram, the time it takes each loop to run.
*/
@Override
public void simpleUpdate(float tpf) {
// not used
}
@Override
public void simpleRender(RenderManager rm) {
// not used
}
public static void main(String[] args) {
MenuScreen app = new MenuScreen();
app.start();
}
/**
* Helper method to initialize and configure Nifty GUI.
*/
private void initNifty() {
mNiftyDisplay = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, guiViewPort);
mNifty = mNiftyDisplay.getNifty();
guiViewPort.addProcessor(mNiftyDisplay);
// If this is being run on a desktop then load the desktop main menu.
if (Strings.OS_NAME.contains("windows") || Strings.OS_NAME.contains("mac") || Strings.OS_NAME.contains("linux")) {
mNifty.fromXml("Interface/XML/DesktopMenuScreenGui.xml", "start", new MenuScreen().new MenuScreenGui());
}
// If its an Android device load the mobile main menu.
else if (Strings.OS_NAME.contains("android")) {
mNifty.fromXml("Interface/XML/MobileMenuScreenGui.xml", "mobile", new MenuScreen().new MenuScreenGui());
}
}
//**************
// Inner Classes
//**************
/**
* © Jason Crosby 2012 <p>
*
* This class handles all the GUI interactions like button clicks.
*
* @author Jason Crosby
*/
public class MenuScreenGui implements ScreenController, EventTopicSubscriber<MenuItemActivatedEvent>,
AppState {
@Override
public void initialize(AppStateManager stateManager, Application app) {
}
@Override
public void cleanup() {
}
@Override
public boolean isEnabled() {
return false;
}
@Override
public boolean isInitialized() {
return false;
}
@Override
public void postRender() {
}
@Override
public void setEnabled(boolean active) {
}
@Override
public void stateAttached(AppStateManager stateManager) {
}
@Override
public void stateDetached(AppStateManager stateManager) {
}
@Override
public void render(RenderManager rm) {
}
@Override
public void update(float tpf) {
}
@Override
public void bind(Nifty nifty, Screen screen) {
// not used
}
@Override
public void onEndScreen() {
// not used
}
@Override
public void onStartScreen() {
// not used
}
@Override
public void onEvent(String string, MenuItemActivatedEvent t) {
}
//**************
// Class methods
//**************
/**
* Called when the play button is clicked.
*/
public void playButton() {
}
/**
* Called when the high scores button is clicked.
*/
public void highScoresButton() {
}
/**
* Called when the settings button is clicked.
*/
public void settingsButton() {
}
public void quitButton() {
showDialog();
}
/**
* Called when the rate button is clicked. Only Available on mobile.
*/
public void rateButton() {
}
/**
* Called when the feedback button is clicked. Only on mobile devices.
*/
public void feedbackButton() {
}
/**
* Called when the help button is clicked.
*/
public void helpButton() {
}
/**
* Called when the dialog needs to be shown.
*/
public void showDialog() {
System.out.println("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW");
popup = new Nifty().createPopup("popup");
System.out.println("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
//Menu myMenu = popup.findNiftyControl("#menu", Menu.class);
//myMenu.setWidth(new SizeValue("100px")); // must be set
//myMenu.addMenuItem("Click me!", new menuItem("menuItemid", "blah blah")); // menuItem is a custom class
//mNifty.subscribe(mNifty.getCurrentScreen(), myMenu.getId(), MenuItemActivatedEvent.class, this);
mNifty.showPopup(mNifty.getCurrentScreen(), popup.getId(), null);
}
public void clsoseDialog() {
}
/**
* Used to return a String to the Nifty xml file.
*
* @param name The name key associated with the String.
* @return The String associated with the key.
*/
public String getString(String name) {
if (name.equals("play")) {
return Strings.PLAY_BUTTON;
}
else if (name.equals("high_score")) {
return Strings.HIGH_SCORES_BUTTON;
}
else if (name.equals("settings")) {
return Strings.SETTINGS_BUTTON;
}
else if (name.equals("quit")) {
return Strings.QUIT_BUTTON;
}
else if (name.equals("rate")) {
return Strings.RATE_BUTTON;
}
else if (name.equals("feedback")) {
return Strings.FEEDBACK_BUTTON;
}
else if (name.equals("rules")) {
return Strings.RULES_BUTTON;
}
return null;
}
}
}
What happens is I click on the quit button which calls the quitButton()
method. That works fine. That in turn invokes showDialog()
which is where the problem is. In the showDialog()
method is this line popup = new Nifty().createPopup("popup");
and it is at that line which mNifty
is null when it shouldn't be. Any assistance is appreciated.
The line
popup = new Nifty().createPopup("popup");
does not use mNifty
. It creates a new instance of Nifty
and then calls creatPopup()
on this new instance. Since earlier you initialized mNifty
by calling what looks like a factory method
mNifty = mNiftyDisplay.getNifty();
it is quite possible that obtaining a Nifty
via new
does not return a completely initialized instance. Since you haven't posted the code for Nifty
it is unclear what is happening.
I would double-check to make sure that creating a Nifty
via new
will return a fully initialized instance, and that you really wanted a new instance here.