Nifty markForRemoval Help/Possible Bug? [Solved]

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?

1 Like

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, :slight_smile:

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. :slight_smile:

Can you please post your error message anyway.

No problem, but as I said it’s exactly the same. :slight_smile:

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. :slight_smile:



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. :slight_smile:



Thanks again for your quick answers, guys. :slight_smile: