How do I get the canvas to update in a for or while loop?

The purpose of the code is to create a set of colored boxes based on columns and rows. (Programming exercise for my students). What happens is that it produces the colored boxes all at once; rather than one at a time.

If I don't use the for/while loops and use variables with if/then. It works. It appears that the loop must complete before the canvas is redrawn. I have tried push/pop matrix; redraw(); and other variations.

What is the difference of being in the loop?

See Code Below:

// Variable Declarations -- Global
int[] my_color = new int[3]; // Array with 3 elements
int[] box_size = new int[3]; // Array with 2 elements
// Define how many rows and columns
int num_col = 5;
int num_row = 6;
// Set display size
int x_size = 800;
int y_size = 800;
// Define minimum margin around area
int margin = 10;
// Define Background Color
color bk_color = #7f7897;

// ------------------------
// the settings loop is new in this version 
//     of processing just for setting the screen size
//
void settings() {
  size(x_size,y_size,P2D);
}

void setup() {
  //noLoop(); // Run the Draw Area just once
  background(255, 204, 0);
  frameRate(30);
  noStroke();
  smooth();
}

void draw() {
  background(255, 204, 0);
  // Get the default box size
  box_size = size_bx(x_size,y_size,margin,num_col,num_row);
  for ( int y_loop = margin; y_loop <= (y_size - margin - box_size[1]) ; y_loop = y_loop + box_size[1]) {
      for (int x_loop = margin; x_loop <= (x_size - margin - box_size[0]); x_loop = x_loop + box_size[0]) {
       // println("Box Coordinates: x=" + x_loop + " y=" + y_loop);

          // Get a Random Color
          my_color = rnd_color();
          // Set Fill color to random Color
          fill(my_color[0],my_color[1],my_color[2]);
          // Draw Box with proper dimensions
          rect(x_loop,y_loop, box_size[0],box_size[1]);
          // Wait a short time between boxes
          delay(60);


      } // end x_loop

  } // end y_loop


} // End Draw



int[] rnd_color(){
  int[] r_color = new int[3];
  r_color[0] = int(random(0,255));
  r_color[1] = int(random(0,255));
  r_color[2] = int(random(0,255));
  return r_color;
}

int[] size_bx(int x, int y, int marg, int col, int row) { 
  int[] box_temp = new int[2]; //Local Variables
    box_temp[0] = int (((x-(2*marg))/col));
    box_temp[1] = int (((y-(2*marg))/row));
    return box_temp;

}
Tagged:

Answers

  • edited July 2016

    The draw() method is drawn to an off-screen buffer. The buffer is then displayed once the draw() method has finished. That means you can't see the intermediate stages as the buffer is being drawn, only the end result.

    You need to format your code for this forum to display it correctly.

  • edited July 2016

    I understand that. But why is it different in a loop v. variables?

    If I write the same code but don't use a loop: for() or while() the buffer seems to update as expected.

  • the screen is only updated once at the end of draw.

    so everything that happens in a for() or while() loop is added to the internal canvas that is put to the screen only later at the end of draw()

  • Why does this work as expected and the for() doesn't?

    // Name: Colored Boxes
    // Purpose: To create a boxes with random colors
    // Date: 07/07/2016
    // Version: 1.0
    // Author: Colin Bitterfield
    // ------------------
    // Variable Declarations -- Global
    int[] my_color = new int[3]; // Array with 3 elements
    int[] box_size = new int[3]; // Array with 2 elements
    // Define how many rows and columns
    int num_col = 5;
    int num_row = 6;
    // Set display size
    int x_size = 800;
    int y_size = 800;
    // Define minimum margin around area
    int margin = 10;
    // Define Background Color
    color bk_color = #7f7897;
    // Define Loops
    int y_loop;
    int x_loop;
    
    // ------------------------
    // the settings loop is new in this version 
    //     of processing just for setting the screen size
    //
    void settings() {
      size(x_size,y_size,P2D);
    }
    
    void setup() {
      //noLoop(); // Run the Draw Area just once
      background(255, 204, 0);
      frameRate(30);
      noStroke();
      smooth();
       y_loop = margin;
       x_loop = margin;
      // Get the default box size
      box_size = size_bx(x_size,y_size,margin,num_col,num_row);
    }
    
    void draw() {
        if ((x_loop == margin) && (y_loop==margin)) {
             delay(100);
             background(255, 204, 0); 
        }
              // Get a Random Color
              my_color = rnd_color();
              // Set Fill color to random Color
              fill(my_color[0],my_color[1],my_color[2]);
              // Draw Box with proper dimensions
              rect(x_loop,y_loop, box_size[0],box_size[1]);
              println("x=" + x_loop + " y=" + y_loop);
              // Wait a short time between boxes
              delay(600);
              x_loop = x_loop + box_size[0];
           if (x_loop > (x_size - margin - box_size[0]) ) { 
              x_loop = margin;
              y_loop = y_loop + box_size[1];
           }
           if (y_loop > (y_size - margin - box_size[1])) {
             y_loop = margin;
             x_loop = margin;
    
           }
    
    
    
    } // End Draw
    
    
    
    int[] rnd_color(){
      int[] r_color = new int[3];
      r_color[0] = int(random(0,255));
      r_color[1] = int(random(0,255));
      r_color[2] = int(random(0,255));
      return r_color;
    }
    
    int[] size_bx(int x, int y, int marg, int col, int row) { 
      int[] box_temp = new int[2]; //Local Variables
        box_temp[0] = int (((x-(2*marg))/col));
        box_temp[1] = int (((y-(2*marg))/row));
        return box_temp;
    
    }
    
  • edited July 2016

    I can only repeat what quark and I've already said.

    It is because the internal setup of draw(), how draw() works:

    • the screen is not updated throughout but only at the end of draw() once.

    draw() runs 60 times per second.

    The solution you've shown above uses the fact that draw() in itself loops. Since you draw only one rect each time draw() runs, the rect is immediately shown. That's why it works. That's good.

    When you would use a for-loop within draw() the entire for loop would draw on an internal canvas and you wouldn't see anything. When the for-loop is over and we get to the end of draw() the screen is updated from the internal canvas.

    BTW

    When you hit ctrl-t in processing you get auto-format (indents). I use it all the time.

  • The difference is that you are executing the entire for-loop inside a single call to draw().

    In the code you just posted the variables x_loop and y_loop are updated just once inside draw() then the result is displayed.

    The next time draw() is executed it uses the new versions of the variables which are then updated and the updated image is displayed.

    The next time draw() is executed ...

    and so on.

Sign In or Register to comment.