I have faced rather strange behavior of com.simsilica.lemur.ListBox class.
Here is small app which adds ListBox select and binds simple logic to clicking on select options (just write line to System.out).
package com.example.bug;
import com.jme3.app.SimpleApplication;
import com.jme3.math.Vector3f;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.ListBox;
import com.simsilica.lemur.event.ConsumingMouseListener;
import com.simsilica.lemur.event.MouseEventControl;
import com.simsilica.lemur.style.BaseStyles;
import org.lwjgl.opengl.Display;
import java.util.ArrayList;
import java.util.List;
public class ErrorApp extends SimpleApplication {
public static void main(String[] args){
ErrorApp app = new ErrorApp();
app.start();
}
@Override
public void simpleInitApp() {
List<Item> items = new ArrayList<>();
items.add(new Item("Item1"));
items.add(new Item("Item2"));
items.add(new Item("Item3"));
items.add(new Item("Item4"));
items.add(new Item("Item5"));
/*
items.add(new Item("q"));
items.add(new Item("qq"));
items.add(new Item("qqq"));
items.add(new Item("qqqq"));
items.add(new Item("qqqqq"));
*/
GuiGlobals.initialize(this);
BaseStyles.loadGlassStyle();
GuiGlobals.getInstance().getStyles().setDefaultStyle(BaseStyles.GLASS);
Container itemContainer = new Container();
MouseEventControl.addListenersToSpatial(itemContainer, ConsumingMouseListener.INSTANCE);
itemContainer.setPreferredSize(new Vector3f(Display.getWidth()*0.2f, Display.getHeight()*0.8f, 0));
ListBox<Item> itemList = itemContainer.addChild(new ListBox<>());
for(Item i: items){
itemList.getModel().add(i);
}
itemList.setVisibleItems(15);
itemList.setCellRenderer((value, selected, existing) -> new Label(value.getName()));
itemList.addClickCommands(source -> System.out.println("######## " + source.getSelectionModel().getSelection()));
itemContainer.setLocalTranslation(0, Display.getHeight(), 0);
getGuiNode().attachChild(itemContainer);
}
private class Item{
String name;
public Item (String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString(){
return name;
}
}
}
This one works as expected.
But if we change list of options from:
items.add(new Item("Item1"));
items.add(new Item("Item2"));
items.add(new Item("Item3"));
items.add(new Item("Item4"));
items.add(new Item("Item5"));
to
items.add(new Item("q"));
items.add(new Item("qq"));
items.add(new Item("qqq"));
items.add(new Item("qqqq"));
items.add(new Item("qqqqq"));
only clicking on the last element ("qqqqq’) will trigger writing to System.out.
So I have two questions:
- What is going on here?
- What is the correct way to implement such logic?
P.S. probably it is somehow related to adding CellRender - at least when I comment out line:
itemList.setCellRenderer((value, selected, existing) -> new Label(value.getName()));
app works as expected.