Clearing an ArrayList

I’ve around this issue a few times. I have a particle system that contains an ArrayList of particles. I use a separate window for the interface programmed using Control P5.

usually my particle system lies under a boolean, and that boolean is activated/deactivated by a cp5 toggle. every time i toggle it to false, i want the ArrayList inside the particle system to be cleared, so the particle system starts fresh from zero instead of a simple interruption it’s runtime.

so i put a ps.particles.clear(); in the toggle false condition. everytime it crashes and I get IndexOutOfBoundsException. it also happened to me with a bang and a button.

what is the most efficient way to really clear an ArrayList?

here is the code with whats going on.

main code

import controlP5.*;

ControlFrame cf;
RingSystem r;

//RING
boolean isRing=false;
PVector cPos;

void settings() {
  size(1024, 1024, P3D);
}

void setup() {
  //CONTROLP5
  cf =new ControlFrame(this, 400, displayHeight, "MENU", width, height);
 //RING SETUP
  cPos=new PVector(width/2, height/2, 0);
  r=new RingSystem(cPos);
}

void draw(){
  if (isRing) {
    if (frameCount%30==0) r.addRing();
    r.display();
  }
}

Ring System

class RingSystem{
 ArrayList<Ring> rings;
 PVector origin;
 RingSystem(PVector _origin){
   rings=new ArrayList<Ring>();
   origin=_origin.copy();
 }
 
 void addRing(){
  rings.add(new Ring(origin)); 
 }
 
 void display(){
   for(int i=rings.size()-1; i>0; i--){
    Ring r=rings.get(i);
    r.update();
    r.display();
    if(r.isDead()){
     rings.remove(i); 
    }
   }
 }
}

Control Frame

    cp5.addToggle("ringToggle")
      .setPosition(160, 50)
      .setSize(80, 80)
      .setValue(false)
      ;
  void ringToggle(boolean toggle) {
    if (toggle==true) {
      isRing=true;
    } else {
      isRing=false;
      
      //r.rings.clear();
      for (int i=0; i<r.rings.size(); i++) {
        Ring ri=r.rings.get(i);
        r.rings.remove(i);
      }
    }
  }
}
1 Like

In the ringToggle(boolean) method use r.rings.clear() it will not throw an IndexOutOfBoundsException exception, that is from somewhere else.

I suspect that the exception is thrown from the display() method.

Also I think the loop condition should be i > = 0 otherwise the first ring will never be updated.

Look at the exception stack trace and follow it down, can you see the method where the exception is thrown, if not copy and paste the trace here.

I also assumed that display() is causing this.

You could set a cleared boolean to true and in display() within the for loop check it and on true leave with return;

hi chisir
i>=0 doesn’t clear the array, just deactivates it. when turned on again, it continues from where it stopped.

using r.rings.clear() it returns

Sep 20, 2018 1:24:32 PM controlP5.ControlBroadcaster printMethodError
SEVERE: An error occured while forwarding a Controller event, please check your code at ringToggle
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at controlP5.ControlBroadcaster.invokeMethod(Unknown Source)
	at controlP5.ControlBroadcaster.callTarget(Unknown Source)
	at controlP5.ControlBroadcaster.broadcast(Unknown Source)
	at controlP5.Controller.broadcast(Unknown Source)
	at controlP5.Toggle.setState(Unknown Source)
	at controlP5.Toggle.setValue(Unknown Source)
	at controlP5.Toggle.setValue(Unknown Source)
	at dome_004$ControlFrame.setup(dome_004.java:356)
	at processing.core.PApplet.handleDraw(PApplet.java:2404)
	at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
	at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
Caused by: java.lang.NullPointerException
	at dome_004$ControlFrame.ringToggle(dome_004.java:467)
	... 15 more

using, erasing one by one

for (int i=0; i<r.rings.size(); i++) {
        Ring ri=r.rings.get(i);
        r.rings.remove(i);
      }

returns

Sep 20, 2018 1:27:21 PM controlP5.ControlBroadcaster printMethodError
SEVERE: An error occured while forwarding a Controller event, please check your code at ringToggle
java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at controlP5.ControlBroadcaster.invokeMethod(Unknown Source)
	at controlP5.ControlBroadcaster.callTarget(Unknown Source)
	at controlP5.ControlBroadcaster.broadcast(Unknown Source)
	at controlP5.Controller.broadcast(Unknown Source)
	at controlP5.Toggle.setState(Unknown Source)
	at controlP5.Toggle.setValue(Unknown Source)
	at controlP5.Toggle.setValue(Unknown Source)
	at dome_004$ControlFrame.setup(dome_004.java:356)
	at processing.core.PApplet.handleDraw(PApplet.java:2404)
	at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
	at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
Caused by: java.lang.NullPointerException
	at dome_004$ControlFrame.ringToggle(dome_004.java:468)
	... 15 more

by creating a boolen cleared you mean

  boolean cleared() {
    if (rings.size()==0) {
      return true;
    } else {
      return false;
    }
  }
  void display() {
    if (cleared()) {
      for (int i=rings.size()-1; i>0; i--) {
        Ring r=rings.get(i);
        r.update();
        r.display();
        if (r.isDead()) {
          rings.remove(i);
        }
      }
    }
  }

Does it work?

I meant something different.

More like

boolean cleared = false; as a global variable

r.rings.clear();
cleared = true; 

and in display()

void display(){
   for(int i=rings.size()-1; i>0; i--){
      if(cleared) return; 

Interesting can’t see the IndexOutOfBoundsException exception :slight_smile:
What is also interesting is you get the same exception using clear() or the loop, so use clear()

What is interesting is the java.lang.reflect.InvocationTargetException. This is caused when it can’t find the method to execute.

Looking at the rest of the stack trace I see

	at dome_004$ControlFrame.setup(dome_004.java:356)
	at processing.core.PApplet.handleDraw(PApplet.java:2404)

It seems that the PApplet’s draw() method is being called before the controlFrame setup() which probably means that the toggle switch is not been configured so the ringToggle method is not been ‘set’. Looking at the rest of the trace seems to confirm this

Caused by: java.lang.NullPointerException
	at dome_004$ControlFrame.ringToggle(dome_004.java:468)

Sorry for qll the seems and maybes I am not familiar with the inner workings of controlP5, being more used to G4P.

There is another possibility and that is because your cp5 toggle is on a cp5 control frame, effectively a second window. Again depending on controlP5 implements the ControlFrame. If it does it in a similar manner to G4P then each window has its own event handling thread so they can get out of sync.

You might try and read this discussion.

1 Like

i’ve opened up a request on controlp5’s github. who knows when they will answer.
also the ControlP5frames example is not working. i’m using processing 3.4

for right now i’ll just change the toggle to control particle spawning, instead of clearing the arraylist, since adding a ControlListener didn’t work at all

1 Like

That’s not the cause of that exception. It means the method being invoked is throwing an exception. Neither is draw being called before setup.

My guess is that it’s because the line constructing the ControlFrame needs moving to the end of setup so that the ring system is constructed first. This may not be a complete fix if threading is involved though.

This fix, instatiating the ControlFrame for last in the setup, really worked.
didn’t survived a lot of vandalism but cleared the function anyway.