I’m trying to dynamically update a Nifty panel with labels. I was looking in the MonkeyZone code, and I tried this method (based off of it) to update my gui:
[java]public void updatePlayers() {
app.enqueue(new Callable<Void>() {
public Void call() throws Exception {
Screen screen = nifty.getScreen(“lobby”);
Element panel = screen.findElementByName(“layer”).findElementByName(“panel”).findElementByName(“player_panel”);
Iterator idIt = panel.getElements().iterator();
while(idIt.hasNext()) {
((Element)idIt.next()).markForRemoval();
}
for (String name : names) {
TextCreator labelCreator = new TextCreator(“unknown_player”);
labelCreator.setFont(“Interface/Fonts/Kroftsmann.fnt”);
labelCreator.setStyle(“nifty-label”);
labelCreator.setText(name);
labelCreator.create(nifty, screen, panel);
}
return null;
}
});
}[/java]
This code breaks, however, if I use the markForRemoval() method. If I comment that method out, my GUI works fine (albeit it constantly adds the same name due to no removals). I get the exception:
[java]SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at de.lessvoid.nifty.elements.Element.onEndScreen(Element.java:2013)
at de.lessvoid.nifty.Nifty$ElementRemoveAction.perform(Nifty.java:966)
at de.lessvoid.nifty.Nifty$EndOfFrameElementAction.perform(Nifty.java:1023)
at de.lessvoid.nifty.Nifty.executeEndOfFrameElementActions(Nifty.java:397)
at de.lessvoid.nifty.Nifty.handleDynamicElements(Nifty.java:316)
at de.lessvoid.nifty.Nifty.update(Nifty.java:253)
at com.jme3.niftygui.InputSystemJme.endInput(InputSystemJme.java:89)
at com.jme3.input.InputManager.processQueue(InputManager.java:776)
at com.jme3.input.InputManager.update(InputManager.java:840)
at com.jme3.app.Application.update(Application.java:605)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:225)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)
at java.lang.Thread.run(Thread.java:722)[/java]
The only info I could find on the forums was here.
Any help?
Thanks
Hmm, I haven’t seen Creator classes being used directly before.
Did you try using TextBuilder?
This method still throws the same error
Code:
[java]app.enqueue(new Callable<Void>() {
public Void call() throws Exception {
Screen screen = nifty.getScreen("lobby");
Element panel = screen.findElementByName("layer").findElementByName("panel").findElementByName("player_panel");
Iterator idIt = panel.getElements().iterator();
while(idIt.hasNext()) {
((Element)idIt.next()).markForRemoval();
}
for (final String name : names) {
ElementBuilder builder = new TextBuilder();
builder.text(name);
builder.font("Interface/Fonts/Kroftsmann.fnt");
builder.height("100%");
builder.width("100%");
panel.add(builder.build(nifty, screen, panel));
}
return null;
}
});[/java]
And its output:
[java]SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at de.lessvoid.nifty.elements.Element.onEndScreen(Element.java:2013)
at de.lessvoid.nifty.Nifty$ElementRemoveAction.perform(Nifty.java:966)
at de.lessvoid.nifty.Nifty$EndOfFrameElementAction.perform(Nifty.java:1023)
at de.lessvoid.nifty.Nifty.executeEndOfFrameElementActions(Nifty.java:397)
at de.lessvoid.nifty.Nifty.handleDynamicElements(Nifty.java:316)
at de.lessvoid.nifty.Nifty.update(Nifty.java:253)
at com.jme3.niftygui.InputSystemJme.endInput(InputSystemJme.java:89)
at com.jme3.input.InputManager.processQueue(InputManager.java:776)
at com.jme3.input.InputManager.update(InputManager.java:840)
at com.jme3.app.Application.update(Application.java:605)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:225)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:149)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:182)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:223)
at java.lang.Thread.run(Thread.java:722)
[/java]
I made a mistake. The above method will work. I had a listener updating the players before the screen was initialized, resulting in the errors. Dumb mistake, ;).
Hey,
I’ve got the same error and the last post in this threads seems to be the solution.
[java]public void updateSelectedWorldObjectDevelopments(){
Screen screen = nifty.getScreen(“start”);
Element selectedWorldObjectDevelopmentsLayer = screen.findElementByName(“selectedWorldObject_Developments”);
removeAllChildElements(selectedWorldObjectDevelopmentsLayer); //If I comment this line out, the application doesn’t crash
float x = 17.5f;
float y;
[two for-loops, nothing special]
ImageBuilder unitBorderImage = new ImageBuilder();
unitBorderImage.x(x + “%”);
unitBorderImage.y(y + “%”);
unitBorderImage.width(“6%”);
unitBorderImage.height(“8%”);
unitBorderImage.filename(“Interface/images/item_highlight.png”);
unitBorderImage.build(nifty, screen, selectedWorldObjectDevelopmentsLayer);
[x and y modifications]
ImageBuilder unitImage = new ImageBuilder();
unitImage.x(x + “%”);
unitImage.y(y + “%”);
unitImage.width(“5.2%”);
unitImage.height(“7.2%”);
[choosing the filename according to the selected object]
unitImage.interactOnClick(“develop(” + i + “,” + r + “)”);
unitImage.build(nifty, screen, selectedWorldObjectDevelopmentsLayer);
[x and y modifications]
[/for-loops]
}[/java]
[java]protected void removeAllChildElements(Element element){
List<Element> children = element.getElements();
for(int i=0;i<children.size();i++){
Element child = children.get(i);
child.markForRemoval();
}
}[/java]
The error message is the same as the one in the first post.
But what do you / does he mean with “before the screen was initialized”?
The screen in my application is already running (So the object itself is initialized^^) and if I just comment out the remove-methods, it works fine (It adds new elements without problems, but doesn’t remove the old ones).
Is there anything I have to check before accessing the elements? (Everything is called in the main/render-thread of jME))
I hope, you understand my question.
Can you please post your error message anyway.
No problem, but as I said it’s exactly the same.
Unfortunately, due to the compiled nifty library, I can’t see which method causes the error at the “lowest” level.
Schwerwiegend: Uncaught exception thrown in Thread[LWJGL Renderer Thread,5,main]
java.lang.NullPointerException
at de.lessvoid.nifty.elements.Element.onEndScreen(Element.java:2013)
at de.lessvoid.nifty.Nifty$ElementRemoveAction.perform(Nifty.java:966)
at de.lessvoid.nifty.Nifty$EndOfFrameElementAction.perform(Nifty.java:1023)
at de.lessvoid.nifty.Nifty.executeEndOfFrameElementActions(Nifty.java:397)
at de.lessvoid.nifty.Nifty.handleDynamicElements(Nifty.java:316)
at de.lessvoid.nifty.Nifty.update(Nifty.java:253)
at com.jme3.niftygui.InputSystemJme.endInput(InputSystemJme.java:113)
at com.jme3.input.InputManager.processQueue(InputManager.java:801)
at com.jme3.input.InputManager.update(InputManager.java:865)
at com.jme3.app.Application.update(Application.java:606)
at com.jme3.app.SimpleApplication.update(SimpleApplication.java:230)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.runLoop(LwjglAbstractDisplay.java:151)
at com.jme3.system.lwjgl.LwjglDisplay.runLoop(LwjglDisplay.java:181)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
at java.lang.Thread.run(Thread.java:722)
May I ask where you call the method ‘updateSelectedWorldObjectDevelopments()’.
Seems for me as at least one child you want to remove is not fully initialized.
Assume for example the following nifty.xml:
[xml]…
<panel id=“toDelete1”>
<!-- some other stuff -->
</panel>
<panel controller=“myController”>
<!-- some other stuff -->
</panel>
<panel id=“toDelete2”>
<!-- some other stuff -->
</panel>
…[/xml]
If one tries to remove the panel with id=“toDelete2” in the bind-method of ‘myController’ it causes the exception:
[java]@Override
public void bind(Nifty nifty, Screen screen, Element element, Properties parameter, Attributes controlDefinitionAttributes) {
Element element = screen.findElementByName(“toDelete1”);
for (Element child : element.getElements())
child.markForRemoval(); // causes NO exception on nifty update
element = screen.findElementByName(“toDelete2”);
for (Element child : element.getElements())
child.markForRemoval(); // causes exception on nifty update
}[/java]
Thanks for your answers.
The controller is defined in the screen-tag:
[xml]<screen id=“start” controller=“engine.gui.ScreenController_IngameMenu”>
[…]
<layer id=“selectedWorldObject_Developments” childLayout=“absolute” visible=“false”>
</layer>
[…]
</screen>[/xml]
The method updateSelectedWorldObj[…] is called from the update()-method from the application.
(There’s no code in the bind-method, if that’s important)
EDIT: I’ve thought about my code structure again and removing all elements and creating new ones is very inefficient - Especially if the amount is limited by the game/gui to a minimum (In my case 8 displayable “developments”/buttons per object).
Now, I create those 8 elements and their interactions at the start of the game and just change the texts, images and visiblities at the runtime.
After all, I think I should be glad about this error - Creating more and more instances would’ve been very unclean code.
Thanks again for your quick answers, guys.