[Solved]Nifty GUI select ListBox Interact: I want item select to call a method

I want my method (blockSelected()) called when the user clicks on a item in the ListBox

is this possible?

niftyxml file

[xml]

<control id="dropDown1" name="listBox" >

<interact onClick="blockSelected()" />

</control>

[/xml]

Class that extends Screen Controller

[java]

public void blockSelected() {

ListBlock dropDown1 = screen.findNiftyControl("dropDown1", ListBox.class);

System.out.println("Selected " + dropDown1.getSelection());

}

[/java]

This has worked on buttons just fine . but I dont want to have to select a item then click on a button.

Also what is the difference between DropDown and ListBox?

A DropDown is a ListBox that drops down and a ListBox does not drop down and is always visible :wink:



You can’t directly add a onClick() to the ListBox control. This is not supported. You should use the eventbus notification to let Nifty call you back when the selection changed.

1 Like

As void said, a ListBox is a simple box with lines of stuff that you fill yourself. A DropDown is a list that, when you click on the arrow on the right, will “drop down” to display the list entered or the number of items defined in the control definition. (You can also refer to this as a combo box if you have done Windows programming.)



The whole thing is a bit involved though.



To have your game act on a selection (clicked on) you have to use the NiftyEventSubscriber. Here’s an example taken from my game. For an easier read I’ve removed several lines as to not confuse anyone more than necessary…



[java]

@NiftyEventSubscriber(id = “idOfListBoxControl”)

public void onListBoxSelectionChanged(final String id,

final ListBoxSelectionChangedEvent<ControlsModelClass> changed) {

// check what the selection’s “object” is

if (changed.getSelection().get(0).getObject() instanceof String) {

// do something if it’s a String

} else {

// do something else if it’s an object

someMethod(changed.getSelection().get(0).getObject());

}

}

[/java]



Here’s a quick explanation.



When you enter items in your ListBox, you might want to use Objects, or any class or type you want really, but that means changing the default way of Nifty of storing those “objects”. In my case I made a class called GameListBoxViewConverter.java. Its content is like that:

[java]

public class GameListBoxViewConverter<T> implements ListBoxViewConverter<T> {



private Object obj;



@Override

public void display(Element element, T item) {

TextRenderer renderer = element.getRenderer(TextRenderer.class);

if (renderer == null) {

return;

}



if (item != null) {

renderer.setText(item.toString());

this.obj = item;

} else {

renderer.setText(“item is null”);

}

}



@Override

public int getWidth(Element element, T item) {

TextRenderer renderer = element.getRenderer(TextRenderer.class);

if (renderer == null) {

return 0;

}

return element.getRenderer(TextRenderer.class).getFont().getWidth(item.toString());

}



public Object getStoredObject() {

return obj;

}

}

[/java]

The class above implements the default “way to store objects” that ListBox will implement in my game. In my case Nifty’s default ListBox storing behavior wasn’t working for me so I made my own.



Now, that’s all good and nice, but how do you enter those? Here’s what it looks like. (Again simplified).

[java]

@SuppressWarnings(“unchecked”)

private void fillListBox(Star star) {

// retrieve the ListBox

ListBox listbox = nifty.getCurrentScreen().findNiftyControl(“stellarBodiesBox”, ListBox.class);

// tell the ListBox what kind of information each “line” will contain.

listbox.setListBoxViewConverter(new GameListBoxViewConverter());



// fill listbox with pertinent info depending on object passed

if (star != null) {

// star is not null, do something with it if you have to

// then add it to the list

listbox.addItem(new ControlsModelClass(star.getXYZ()));

} else {

// do something else

}

}

[/java]



Sorry for the long post. As I said, it’s a bit involved. But it works quite nicely. I’ve reread the explanations and there are some things that I left open for you to discover. Hopefully that’ll give you a head start.

Forgot to paste the ControlsModelClass to give you an idea of what’s going on when you add an item.



[java]

public class ControlsModelClass {



private String label;

private Object obj;



public ControlsModelClass(final Object obj) {

label = obj.toString();

this.obj = obj;

}



public Object getObject() {

return obj;

}



@Override

public String toString() {

return label;

}

}

[/java]

… and if you just want to add plain Strings to the ListBox you could skip all of that Model and ViewConverter stuff and simply add the Strings to the ListBox:



[java]ListBox listbox = nifty.getCurrentScreen().findNiftyControl(“listBoxId”, ListBox.class);

listbox.addItem(“a”);

listbox.addItem(“b”);

listbox.addItem(“c”);[/java]



This will work as well and in the Event you will get the selected String back.



A special ListBoxViewConverter is only necessary when the objects you add to the ListBox don’t have an appropiate toString() method. When you don’t set a special ListBoxViewConverter then Nifty will simply call .toString() to get the text the Listbox should display.



You’ll need a special ListBoxViewConverter - like in madjacks example - only when you want to use some other getter to get the text or when you want to display not only a text but additional stuff for each listbox item. Ractoc’s Chatcontrol internally uses a ListBox too but displays an image and a text for each Listbox item.

This is what I ended up doing

I have 3 list box on the screen

listBox1

listBoxModel

listBoxGroup

[xml]



<control id="listBoxModel" name="listBox" displayItems="12"/>



[/xml]

[java]

public class InventoryScreenController implements ScreenController{



public void blockSelected(String listBoxName) {

ListBox listBox = findDropDownControl(listBoxName);



}



@NiftyEventSubscriber(pattern = "listBox.*")

public void onListBoxSelectionChanged(final String id,

final ListBoxSelectionChangedEvent<String> changed) {

blockSelected(id);

}

[/java]



Thanks for your help

Thanks for your example too :slight_smile:



Your example and the posts of MadJack above made me update the ListBox documentation in the Nifty Wiki.



You can find in-depth explanations / how-tos at the bottom of that page on how to actually use the ListBox in different ways :slight_smile:



Maybe MadJack and I (as well as other people interessted in helping the wiki) can do something similar for the other controls as well …