DropDown not populating

Hi everyone,

Was wondering if someone could help me get my resolution selection drop down to work. When I step through the code in the debugger, I can see that 17 items are added to the dropdown’s items. But they dont show up, even if I select one myself. The strings are non zero length.

Below is my code:

[java]public void bind(Nifty nifty, Screen screen)

{

CheckBox fullScreenCheckBox = screen.findNiftyControl(“fullScreenCheckbox”, CheckBox.class);

CheckBox vsyncCheckBox = screen.findNiftyControl(“vsyncCheckbox”, CheckBox.class);

DropDown<String> resolutionDropDown = screen.findNiftyControl(“resolutionDropdown”,DropDown.class);

fullScreenCheckBox.setChecked(settings.isFullscreen());

vsyncCheckBox.setChecked(settings.isVSync());

device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

modes = device.getDisplayModes();

resolutionDropDown.addAllItems(getResolutions(modes));

resolutionDropDown.selectItemByIndex(1);

}[/java]

and the XML:

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

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

<useStyles filename=“nifty-default-styles.xml” />

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

<screen id=“options” controller=“GUI.OptionsMenu”>

<layer id=“layer” backgroundColor="#000f" childLayout=“center”>

<panel id=“panel” height=“75%” width=“50%” align=“center” valign=“center” backgroundColor="#000f" childLayout=“vertical” visibleToMouse=“true”>

<panel id=“headingPanel” childLayout=“center” align=“center” valign=“center” color=“000f” height=“25%” width=“100%” >

<text id=“optionsText” font="…/assets/Fonts/Vinque_32B.fnt" color="#8B0000ff" text=“Options” align=“center” valign=“center” size=“24” width=“100%” height=“100%”/>

</panel>

<panel id=“fullScreenPanel” childLayout=“horizontal” align=“center” valign=“center” color=“000f” height=“12%” width=“100%”>

<text id=“fullScreenText” font="…/assets/Fonts/Vinque_24B.fnt" color="#C6E2FFff" text=“Full Screen” align=“center” valign=“center” size=“24” width=“100%” height=“100%” />

<control name=“checkbox” id=“fullScreenCheckbox” checked=“true” align=“center” valign=“center” ></control>

</panel>

<panel id=“vsyncPanel” childLayout=“horizontal” align=“center” valign=“center” color=“000f” height=“12%” width=“100%”>

<text id=“vsycText” font="…/assets/Fonts/Vinque_24B.fnt" color="#C6E2FFff" text=“V Sync” align=“center” valign=“center” size=“24” width=“100%” height=“100%” />

<control name=“checkbox” id=“vsyncCheckbox” checked=“true” align=“center” valign=“center” ></control>

</panel>

<panel id=“resolutionPanel” childLayout=“horizontal” align=“center” valign=“center” color=“000f” height=“12%” width=“100%”>

<text id=“resolutionText” font="…/assets/Fonts/Vinque_24B.fnt" color="#C6E2FFff" text=“Resolution” align=“center” valign=“center” size=“24” width=“100%” height=“100%” />

<control name=“dropDown” id=“resolutionDropdown” checked=“true” align=“center” valign=“center” ></control>

</panel>

<panel id=“applySettingsPanel” childLayout=“center” align=“center” valign=“center” color=“000f” height=“15%” width=“100%”>

<text id=“applySettingsText” font="…/assets/Fonts/Vinque_32B.fnt" color="#C6E2FFff" text=“Apply Settings” align=“center” valign=“center” size=“24” width=“100%” height=“100%” />

<interact onClick=“applySettings()”/>

<effect>

<onHover name=“border” color="#822f" post=“true” />

<onEnabled name=“renderQuad” startColor="#2228" endColor="#2220" post=“true” length=“150” />

<onDisabled name=“renderQuad” startColor="#2220" endColor="#2228" post=“true” length=“150” />

</effect>

</panel>

<panel id=“backPanel” childLayout=“center” align=“center” valign=“center” color=“000f” height=“15%” width=“100%”>

<text id=“backText” font="…/assets/Fonts/Vinque_32B.fnt" color="#C6E2FFff" text="…Back" align=“center” valign=“center” size=“24” width=“100%” height=“100%” />

<interact onClick=“back()”/>

<effect>

<onHover name=“border” color="#822f" post=“true” />

<onEnabled name=“renderQuad” startColor="#2228" endColor="#2220" post=“true” length=“150” />

<onDisabled name=“renderQuad” startColor="#2220" endColor="#2228" post=“true” length=“150” />

</effect>

</panel>

</panel>

</layer>

</screen>

</nifty>

[/xml]

Yes I know jMonkeyEngine has a built in settings dialog, I prefer to use internal settings from a look and feel point of view. Here is a screenshot, WIP obviously.





While I remember, one more question:



The TextColor effect - it doesnt seem to work. Doesnt change the colour of the text. As you can see, the font I use allows for its colour to be changed.



Also, what is the recommended way for changing GUI screens and hiding the GUI when not needed? I’m using fromXML to load the screens because gotoScreen could not find my start screen (its id is start, it was loaded from the XML prior to calling gotoScreen). I use nifty.exit() to hide the gui.

Hi,

For the dropDown. That’s strange. It should work :slight_smile:

  • does your method getResolutions(…) return a list of String ?
  • I’m doing something similar in my project.

    Have you tried to populate the drop down during the onStartScreen(…) instead of the bind(…)

    I don’t know if it will change anything…

    [java]

    private DropDown<String> resolutionDropDown ;

    public void bind(Nifty nifty, Screen screen)

    {

    CheckBox fullScreenCheckBox = screen.findNiftyControl("fullScreenCheckbox", CheckBox.class);

    CheckBox vsyncCheckBox = screen.findNiftyControl("vsyncCheckbox", CheckBox.class);

    this.resolutionDropDown = screen.findNiftyControl("resolutionDropdown",DropDown.class);

    fullScreenCheckBox.setChecked(settings.isFullscreen());

    vsyncCheckBox.setChecked(settings.isVSync());

    device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();

    }

    public final void onStartScreen()

    {

    modes = device.getDisplayModes();

    resolutionDropDown.addAllItems(getResolutions(modes));

    resolutionDropDown.selectItemByIndex(1);

    }

    [/java]

Also, what is the recommended way for changing GUI screens and hiding the GUI when not needed? I’m using fromXML to load the screens because gotoScreen could not find my start screen (its id is start, it was loaded from the XML prior to calling gotoScreen). I use nifty.exit() to hide the gui.

I'm now using this method :
each of my GUI are controls ( and not screen anymore ) and I use only one screen inside which I add the GUI I need with methods like
[java]
ControlBuilder builder = new ControlBuilder( "myControlName" );
Element myGUI = builder.build( nifty, screen, myOverlayPanel );
[/java]
That way I can easily destroy the GUI I don't want, hide them when they are not needed but will serve in the future, etc...
[java]
myGUI.markForRemoval();
myGUI.hide()
[...]
[/java]
I think it's the most efficient and flexible way to manage multiple GUI.
Only drawback :
If one of your controlDefinition is corrupted ( you miss to close a panel tag for example ), Nifty will not initialize itself.
I may not be a real drawback in fact : If your Nifty initialize, it means all of your control definition are 'correct'.

I tried to do it in the constructor, but I dont think any of the elements existed at that point. Will try onStartScreen. Whats puzzling is that the checkboxes for vsync and fullscreen change correctly.



The getResolutions function is in fact borrowed from the settings dialog, it returns an ArrayList of Strings. The original returned an array of Strings, I changed it to an array list because addAllItems expects a list of Strings.



I’ll look into that, at the moment I like having a separate screen controller for my screens to handle the custom logic needed for each screen. I could make it more generic though, something like clicking on a panel calls loadScreen(“newPanelName”) instead of loadSinglePlayerMenu, for instance.



What I also want to do is write something that will process the XML files and do string replacements from a string table. This will help with language localization.

For internationalisation, there is already something available in Nifty.

I havn’t tried it yet.

Thanks, that would help.

The other thing I need to do is define my own styles, and maybe even custom controls. I want to have a central place to change fonts and colours from, instead of specifying them on the elements, as they are now. Maybe I’ll do that tonight before doing any other GUI work, as well as the localization thing.

Does everything have to have a style? I tried running without a style last night, as well as defining my own button style but still importing the rest of the styles. Neither seemed to work. I suppose I’ll have to redefine every style mentioned in the default style.



EDIT: Having thought about this a bit more, I dont think nifty’s localization solution is adequate for me, because I need string substitution for more than just localization. I’ll have dialogs and popups with item descriptions, these need to be populated dynamically and not hardcoded. I’ll have to write a component to automatically insert the correct string based on localization settings.

No, you don’t have to define a style for controls.

The style helps you define multiple appearance for the same control.

Inside a controlDefinition, you have to define :

  • the name of the control
  • which JAVA class will handle it.
  • The elements it contains and their locations.

    You can also define the appearance directly inside the control or define a default style :

    Solution 1:

    [java]

    <controlDefinition name=“myControl” controller=“package.ControllerClass” >

    <panel height=“200px” width=“100px” childLayout=“vertical” >

    <text id=“text1” height=“40px” width=“100%” text=“text 1” font=“Fonts/Vinque_32B.fnt” />

    <panel height=“5px” />

    <text id=“text2” height=“40px” width=“100%” text=“text 2” font=“Fonts/Vinque_32B.fnt” />

    <panel height=“5px” />

    <text id=“text3” height=“40px” width=“100%” text=“text 3” font=“Fonts/Vinque_32B.fnt” />

    </panel>

    </controlDefinition>

    [/java]

    Solution 2:

    Inside the control part :

    [java]

    <controlDefinition name=“myControl” style=“myStyle” controller=“package.ControllerClass” >

    <panel style="#panel" >

    <text id=“text1” style="#text" text=“text 1” />

    <panel height=“5px” />

    <text id=“text2” style="#text" text=“text 2” />

    <panel height=“5px” />

    <text id=“text3” style="#text" text=“text 3” />

    </panel>

    </controlDefinition>

    [/java]

    Inside the style part :

    [java]

    <style id=“myStyle#panel”>

    <attributes height=“200px” width=“100px” childLayout=“vertical” />

    </style>

    <style id=“myStyle#text”>

    <attributes height=“40px” width=“100%” font=“Fonts/Vinque_32B.fnt” />

    </style>

    [/java]

    If you want to use custom controls / styles, you have to declare them in your Screen file :

    [java]

    <useStyles filename=“assets/Templates/Styles/ae-styles.xml” />

    <useControls filename=“assets/Templates/Controls/ae-controls.xml” />

    [/java]

    And in those file you define all the control/style you need.

    [java]

    <?xml version=“1.0” encoding=“UTF-8”?>

    <nifty-controls>

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

    <useControls filename=“assets/Templates/Controls/myControl.xml” />

    […]

    </nifty-controls>

    [/java]

    [java]

    <?xml version=“1.0” encoding=“UTF-8”?>

    <?xml version=“1.0” encoding=“UTF-8”?>

    <nifty-styles>

    <useStyles filename=“nifty-default-styles.xml” />

    <useStyles filename=“assets/Templates/Styles/myStyle.xml” />

    […]

    </nifty-styles>

    [/java]

    ----

    One thing about the path you need to define for your ressources.

    Nifty use the assetManager of your JME application, so there is no need to define the path from the position of your XML.

    You can replace

    [java]

    font="…/assets/Fonts/Vinque_24B.fnt"

    [/java]

    by

    [java]

    font=“Fonts/Vinque_24B.fnt”

    [/java]

    useControls and useStyles are the only two exception. It seems you need to define to path from the root of your project.

    ( Perhaps it has been corected since I saw it. )



    If you want to dynamicly update the text of your control, you can do something like this :

    [java]

    <controlDefinition name=“myControl” controller=“package.MyController” >

    <panel style=height=“100%” width=“100%” childLayout=“center” >

    <text id=“text” text="" height=“100%” width=“100%” font=“Fonts/Vinque_32B.fnt” text="" />

    </panel>

    </controlDefinition>

    [/java]

    The controller :

    [java]

    public class MyController implements Controller

    private Element textElement;

    private String rawText;

    @Override

    public void bind ( final Nifty nifty,

    final Screen screenParam,

    final Element element,

    final Properties parameter,

    final Attributes controlDefinitionAttributes )

    {

    this.textElement= element.findElementByName(“text”);

    rawText = parameter.getProperty( “text” );

    if( rawText == null )

    rawText = “”;

    }

    @Override

    public void init(Properties arg0, Attributes arg1)

    {

    update();

    }

    public void update()

    {

    String text = rawText;

    //Convert the balise I don’t want

    if( text.contains( “<Name>” ) )

    text = text.replace( <Name>, “The name I want” );

    //Set it to the text element

    textElement.getRenderer( TextRenderer.class ).setText( text );

    }

    [/java]

    And with that, you just have to change your lines :

    [java]

    <text text=“Hello <Name>” height=“20px” width=“60px” font=“Fonts/Vinque_32B.fnt” />

    [/java]

    by

    [java]

    <control name=“myControl” text=“Hello <Name>” height=“20px” width=“60px” />

    [/java]

    It should work :slight_smile:

    ( I just wrote the JAVA part, there may have some syntax mistake inside it )