Trouble accessing Nifty Controls

Good day Monkeys,

I have written a game with multiple screens, the XML follows

<?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">
    <useStyles filename="nifty-default-styles.xml" />
    <useControls filename="nifty-default-controls.xml" />   
    <screen id="start" controller="Reved.MyStartScreen">
        <layer id="background" childLayout="center">
            <image filename="Interface/start-background.png"></image>
        </layer>
        <layer id="foreground" childLayout="vertical">
            <panel id="panel_top" height="5%" width="75%" align="center" childLayout="center">
                <text text="REVED - An Exciting Motor Racing Game" font="Interface/Fonts/Default.fnt" width="100%" height="100%" />               
            </panel>
            <panel id="panel_1" height="15%" width="75%" align="center" childLayout="horizontal">
                <control name="button" label="Practice" id="btnPractice" align="center" valign="center" visibleToMouse="true" >
                       <interact onClick="Practice()" />  
                </control>
                <control  name="button" label="Race" id="btnRace" align="center" valign="center" visibleToMouse="true" >                        
                </control>               
            </panel>
            <panel id="panel_mid" height="50%" width="75%" align="center" childLayout="center">
                <text text="" font="Interface/Fonts/Default.fnt" width="100%" height="100%" wrap="true" />
            </panel>
            <panel id="panel_bottom" height="25%" width="75%" align="center" childLayout="horizontal" >
                <panel id="panel_bottom_left" height="50%" width="30%" valign="center" childLayout="center">
                    <control name="button" label="Start" id="StartButton" align="center" valign="center" visibleToMouse="true" >
                        <interact onClick="StartGame()" />
                    </control>
                </panel>                         
                <panel id="panel_bottom_centre" height="50%" width="50%" valign="center" childLayout="center">
                    <control name="label" id="loading" width="30%" text=" " color="#00ff00" /> 
                </panel>                
                <panel id="panel_bottom_right" height="50%" width="30%" valign="center" childLayout="center">
                    <control name="button" label="Quit" id="QuitButton" align="center" valign="center" visibleToMouse="true" >
                       <interact onClick="QuitGame()" />  
                    </control>
                </panel>
            </panel>
        </layer>
    </screen>
    <useStyles filename="nifty-default-styles.xml" />
    <useControls filename="nifty-default-controls.xml" />      
   <screen id="hud"  controller="Reved.MyStartScreen">
        <layer id="foreground" childLayout="vertical">
           <panel id="blank" width="100%" height="80%"></panel>        
            <panel id="instrument" width="20%" height="20%" valign="bottom" align="center" childLayout="horizontal" backgroundColor="#505050">    
             <!--image filename="Interface/hud-frame.png"></image-->
             <text id="speed" width="100%" textLineHeight="30" height="10%" text="SPEED:000" color="#ffff00" font="Interface/Fonts/TrebuchetMS.fnt"/>
               <image filename="Interface/face1.png" visibleToMouse="true">
                   <interact onMouseOver="getMouseControlValues()" />
               </image>
            </panel>
        </layer>
    </screen>
   <useStyles filename="nifty-default-styles.xml" />
   <useControls filename="nifty-default-controls.xml" />   
   <screen id="RaceParams"  controller="Reved.MyStartScreen">
       <layer id="fore1" childLayout="vertical">     
          <panel id="pop1Pan1" width="100%" height="100%" childLayout="vertical">
           <text id="void1" width="100%" textLineHeight="30" height="10%" text="Set Values" align="center" color="#ffff00" font="Interface/Fonts/TrebuchetMS.fnt"/>
            <text id="DiffLabel" font="Interface/Fonts/Default.fnt" align="center" width="30%" text="Easy------Difficulty Level------Hard" color="#00ff00" />
            <control id="Difficulty" name="horizontalSlider" align="center" min="0.0" max="10.0"  initial="5.0" buttonStepSize="1.0" stepSize="1.0" width="30%" />
            <control id="diffValue" name="label" width="50px" text=" " color="#C5A599" />
            <text id="OppLabel" font="Interface/Fonts/Default.fnt" align="center" width="30%" text="Number of Opponents" color="#00ff00" />
            <control id="nOpponents" name="horizontalSlider" align="center" min="0.0" max="8.0"  initial="4.0" buttonStepSize="1.0" stepSize="1.0" width="30%" />
            <control id="nOpps" name="label" width="50px" text=" " color="#C5A599" />
            <control name="button" label="Race Now" id="RaceButton"  align="center" width="30%" visibleToMouse="true" >
                <interact onClick="StartGame()" />  
            </control>
          </panel>
       </layer>  
   </screen>
</nifty>

My Screen Controller (MyStartScreen.java) is this

package Reved;

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.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.NiftyEventSubscriber;
import de.lessvoid.nifty.controls.ButtonClickedEvent;
import de.lessvoid.nifty.controls.Label;
import de.lessvoid.nifty.controls.Menu;
import de.lessvoid.nifty.controls.MenuItemActivatedEvent;
import de.lessvoid.nifty.controls.NiftyControl;
import de.lessvoid.nifty.controls.Slider;
import de.lessvoid.nifty.controls.SliderChangedEvent;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.elements.render.TextRenderer;
import de.lessvoid.nifty.input.NiftyInputEvent;
import de.lessvoid.nifty.input.NiftyMouseInputEvent;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import de.lessvoid.nifty.tools.Color;
import de.lessvoid.nifty.tools.SizeValue;
import de.lessvoid.xml.xpp3.Attributes;
import java.util.Properties;
import org.bushe.swing.event.EventTopicSubscriber;

/**
 *
 * @author steve
 */
public class MyStartScreen extends AbstractAppState
                           implements ScreenController,
                                      de.lessvoid.nifty.controls.Controller
{
  private ViewPort viewPort;
  private Node rootNode;
  private Node guiNode;
  private AssetManager assetManager;
  private Node localRootNode = new Node("Start Screen RootNode");
  private Node localGuiNode = new Node("Start Screen GuiNode");
  private final ColorRGBA backgroundColor = ColorRGBA.Black;  
  public  Reved app;
  public  Element popup ;
  private AppStateManager stateManager;
  private Nifty nifty;
  private Screen screen;
  
    public MyStartScreen(Reved iapp)
    {
        
       this.rootNode     = iapp.getRootNode();
       this.viewPort     = iapp.getViewPort();
       this.guiNode      = iapp.getGuiNode();
       this.assetManager = iapp.getAssetManager();
       this.app          = iapp ;
    }
    
    @Override
    public void initialize(AppStateManager stateManager, Application  iapp)
    {
        super.initialize(stateManager, iapp);
        //this.app = (Reved) iapp;
           
        rootNode.attachChild(localRootNode);
        guiNode.attachChild(localGuiNode);
        viewPort.setBackgroundColor(backgroundColor);
    
        //TODO: initialize your AppState, e.g. attach spatials to rootNode
        //this is called on the OpenGL thread after the AppState has been attached
    }

    @Override
    public void update(float tpf) {
        //TODO: implement behavior during runtime
        
        InstrumentData() ;
    }

    @Override
    public void cleanup() {
        super.cleanup();
        //TODO: clean up what you initialized in the initialize method,
        //e.g. remove all spatials from rootNode
        //this is called on the OpenGL thread after the AppState has been detached
    }

    @Override
    public void bind(Nifty nifty, Screen screen) {
       // throw new UnsupportedOperationException("Not supported yet.");
    }

    public void onStartScreen() {
       // throw new UnsupportedOperationException("Not supported yet.");
    }

    public void onEndScreen() {
       // throw new UnsupportedOperationException("Not supported yet.");
       // app.stop();
    }
    
    //.............................................
    //..Start the Game
    //.............................................
    
    public void StartGame()
    {
        System.out.println("In Start Game") ;
        
        
        Element niftyElement = app.startNifty.getCurrentScreen().findElementByName("loading");         
        niftyElement.getRenderer(TextRenderer.class).setText("Loading");      
       
        app.simpleInitApp1();   
        app.startNifty.removeScreen("start");
        app.startNifty.gotoScreen("hud");  // switch to the HUD screen
       
       
    }
    
    //..............................................
    //.. Quit the Game
    //..............................................
    
    public void QuitGame()
    {
        System.out.println("Quit button Pressed");
        app.stop();
    }
    
    //............................................
    //..Get the Instrumentation data
    //............................................
    
    public void InstrumentData()
    {
        GetSpeed() ;
    }
    
    public void GetSpeed()
    {
        String sp ;
        
        sp = "SPEED:" + app.speedDisp ;
       
        try
        {
          Element niftyElement = app.startNifty.getCurrentScreen().findElementByName("speed");         
          niftyElement.getRenderer(TextRenderer.class).setText(sp);
        }
        catch(Exception e)
        {
            
        }
    }
    
    /*.................................................
     * .. Get Mouse Control Values
     *.................................................*/
    
    public void getMouseControlValues(Element element, NiftyMouseInputEvent event)
    {
        
        int   xcentre, ycentre ;
        float xvalue, yvalue;
        
        xcentre = element.getX() + element.getWidth()/2;
        ycentre = element.getY() + element.getHeight()/2;
        
        xvalue = event.getMouseX() - xcentre ;
        yvalue = event.getMouseY() - ycentre ;
        xvalue = (xvalue * 0.8f);
        
        app.MouseControl(xvalue, yvalue);
       
      
    }
    
   /*...........................................
    * Adjust game difficulty
    *...........................................*/
    
    @NiftyEventSubscriber(id="Difficulty")
    
    public void DifficultyValue(String id, SliderChangedEvent event)
    {
        String gd ;
        app.gameDifficulty = event.getValue();
        gd = Float.toString(app.gameDifficulty);
        Element niftyElement = app.startNifty.getCurrentScreen().findElementByName("diffValue"); 
        
        niftyElement.getRenderer(TextRenderer.class).setText(gd);
    }
    
    
    /*...........................................
    * Adjust number of Opponents
    *...........................................*/
    
    @NiftyEventSubscriber(id="nOpponents")
    
    public void SetNumberofOpponents(String id, SliderChangedEvent event)
    {
        String nOp ;
        app.nOpponents = (int) event.getValue();
        nOp = Integer.toString(app.nOpponents);
     //   Element niftyElement = app.startNifty.getCurrentScreen().findElementByName("nOpps"); 
        
     //   niftyElement.getRenderer(TextRenderer.class).setText(nOp);
        
        app.startNifty.getCurrentScreen().findNiftyControl("nOpps",Label.class).setText(nOp);  
    }
    
    /*.....................................................
     * ..Show race menu
     *.....................................................*/
    
     @NiftyEventSubscriber(id="btnRace")
     public void ShowRaceMenu(String id, ButtonClickedEvent event)
     {
       
       Screen thisScreen ;
       Slider s;
       Label  l;
  
       app.startNifty.removeScreen("start");
       app.startNifty.gotoScreen("RaceParams");  // switch to the Parameter screen for Race
       
       thisScreen = app.startNifty.getScreen("RaceParams");
       
       System.out.println("ThisScreen=" + thisScreen.getScreenId());
       
       //--Get default values of gameDifficulty, nOpponents and nLaps
       
       float gDiff = app.gameDifficulty;
       int   nOpp  = app.nOpponents;
       
       System.out.println("gDiff= " + gDiff + " nOpp=" + nOpp);
       
       try
       {
         app.startNifty.getCurrentScreen().findNiftyControl("Difficulty",Slider.class).setValue(gDiff);
           
       }
       catch(Exception e)
       {
           System.out.println(e.getMessage());
       }
       
       try
       {
         app.startNifty.getCurrentScreen().findNiftyControl("nOpponents",Slider.class).setValue(nOpp);
       }
        catch(Exception e)
       {
           System.out.println(e.getMessage());
       }
       
       try
       {
         app.startNifty.getCurrentScreen().findNiftyControl("nOpps",Label.class).setText(Integer.toString(nOpp));
       }
        catch(Exception e)
       {
           System.out.println(e.getMessage());
       }
     }
     
     
 

    public void bind(Nifty nifty, Screen screen, Element element, Properties parameter, Attributes controlDefinitionAttributes) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void init(Properties parameter, Attributes controlDefinitionAttributes) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public void onFocus(boolean getFocus) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    public boolean inputEvent(NiftyInputEvent inputEvent) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
 
}

When I click the “Race” button (id=“btnRace”) I switch to the “RaceParams” screen.

The Slider controls id=“Difficulty” and id=“nOpponents” are rendered on that screen.

The problem occurs when I try to set the values of these sliders to a default value (I know I do this in XML but I want to read the settings from elsewhere at runtime).

The code for doing this is in the “ShowRaceMenu” function

   try
       {
         app.startNifty.getCurrentScreen().findNiftyControl("Difficulty",Slider.class).setValue(gDiff);
           
       }
       catch(Exception e)
       {
           System.out.println(e.getMessage());
       }
       
       try
       {
         app.startNifty.getCurrentScreen().findNiftyControl("nOpponents",Slider.class).setValue(nOpp);
       }
        catch(Exception e)
       {
           System.out.println(e.getMessage());
       }
       
       try
       {
         app.startNifty.getCurrentScreen().findNiftyControl("nOpps",Label.class).setText(Integer.toString(nOpp));
       }
        catch(Exception e)
       {
           System.out.println(e.getMessage());
       }

JME3 reports that these controls are not found, but they are rendered on the screen

Aug 07, 2015 7:16:12 AM de.lessvoid.nifty.screen.Screen findNiftyControl
WARNING: missing element/control with id [Difficulty] for requested control class [de.lessvoid.nifty.controls.Slider]
Aug 07, 2015 7:16:12 AM de.lessvoid.nifty.screen.Screen findNiftyControl
WARNING: missing element/control with id [nOpponents] for requested control class [de.lessvoid.nifty.controls.Slider]
Aug 07, 2015 7:16:12 AM de.lessvoid.nifty.screen.Screen findNiftyControl
WARNING: missing element/control with id [nOpps] for requested control class [de.lessvoid.nifty.controls.Label]

Can someone explain why this is not working ?

Print out getCurrentScreen to make sure it is RaceParams for starters

   app.startNifty.removeScreen("start");
      
       app.startNifty.gotoScreen("RaceParams");  // switch to the Parameter screen for Race
       
       thisScreen = app.startNifty.getScreen("RaceParams");
       
       System.out.println("ThisScreen=" + thisScreen.getScreenId());
       
       //--Get default values of gameDifficulty, nOpponents and nLaps
       
       float gDiff = app.gameDifficulty;
       int   nOpp  = app.nOpponents;
       
       System.out.println("CurrentScreen =" + app.startNifty.getCurrentScreen().getScreenId() + " gDiff= " + gDiff + " nOpp=" + nOpp);

Output is CurrentScreen= start

Even though I have removed the start screen and loaded the “RaceParams” screen.

Why is this ?

also if I substitute “thisScreen” for app.startNifty.getCurrentScreen() it still doesn’t work as I get “null” printed out by the catch blocks

Don’t just print the message of the exceptions as that’s one step away from totally useless. Print the WHOLE EXCEPTION.

e.printStackTrace() if you are going to do it this way.

You need to use Nifty’s onStartScreen. There you can check the current screen and populate your settings. That is where Nifty tells you that the screen is now loaded. ShowRaceMenu() just needs to do the transition.

Thanks, I changed it to making the “RaceParameters” as another layer in the Start Screen, and showing and hiding it where necessary. Seems a lot easier to manage that way.

Its easier to have them as separate screens. Your problem is because the transition to the new screen doesn’t happen immediately. As a previous poster said, you need to use the onStartScreen() callback for the screen controller for the new screen.

Thank you, that has given me some good info.