codeav33
codeav33

Reputation: 1

For loop drawing PGraphics in an array [Processing]

I'm trying to build a Drawing Program using Processing. I am currently stuck on using PGrapchics.

When the user draws a rectangle, it shows the shape being drawn. When the user releases their mouse, it then creates a PGraphic of the final shape. I would then like the user to draw on top of that. Here is my problem:

I had to reset the background of the canvas when drawing a rectangle because otherwise, it shows a trail of rectangles. The result is that while the user draws a new rectangle the old ones disappear and come back once the mouse has been releasd

Some thoughts: I would also like to add features where the user can select on a previously drawn rectangle and change it's colour, stroke, send to back, bring to front etc..

To achieve this, I'm storing all drawn rectangles (PGraphics) into an ArrayList which will be drawn via a for loop. This will allow me to adjust the behaviour by moving the PGraphics elements up and down the ArrayList.

PS: Instead of creating my own class of Shape am I better off using PShape?

int startX;
int startY;
int endX;
int endY;
boolean drawing;
int strokeW = 3;
Shape shape;

PGraphics shapeLayer; 
ArrayList<PGraphics> layersList = new ArrayList();

void setup() {
  size(500, 500);
  cursor(CROSS);
  background(255);
  smooth();
}

void draw() {
  strokeWeight(strokeW);
  if (key >= '0' && key <= '9') {
    strokeW = key - '0';
  }
  for(int i = 0; i < layersList.size(); i++) {
    image(layersList.get(i), 0, 0);
  }
  if (drawing) {
    shape.createRectangle();
  }
}


void mousePressed() {
  startX = mouseX;
  startY = mouseY;

  shapeLayer = createGraphics(width, height);
  shapeLayer.beginDraw();
}  

void mouseDragged() {
  drawing = true;
  endX = constrain(mouseX, 0, 500);
  endY = constrain(mouseY, 0, 500); 

  shape = new Shape(startX, startY, endX, endY);
  shapeLayer.clear();
}

void mouseReleased() {
  drawing = false;
  shapeLayer.endDraw();
  layersList.add(shapeLayer);
}  

Here is the Shape Class:

class Shape {
  int startX;
  int startY;
  int endX;
  int endY;

  Shape(int x1, int y1, int x2, int y2) {
    startX = x1;
    startY = y1;
    endX = x2;
    endY = y2;
  }    

  void createRectangle() {
    background(255, 0);
    shapeLayer.strokeWeight(strokeW);
    shapeLayer.rectMode(CORNERS);
    shapeLayer.rect(startX, startY, endX, endY);  
    rectMode(CORNERS);
    rect(startX, startY, endX, endY);

  }

}  

Upvotes: 0

Views: 544

Answers (2)

George Profenza
George Profenza

Reputation: 51837

In addition to Kevin's answer: it does look like you are using another PGraphics buffer to draw into, but the whole sketch could be simpler.

Unless you need an undo/redo mode, where remembering the drawing commands and their order is needed, you can get away with something slightly simpler.

You can find a detailed answer with commented code showing something very similar. You simply need to add the pencil and line modes.

Upvotes: 0

Kevin Workman
Kevin Workman

Reputation: 42176

In the future, please try to narrow your problem down to a MCVE before you post. For example you could have hard-coded it to draw a rectangle when the user drags instead of including all the code for every shape.

But your problem is caused by drawing to the screen and never clearing it out. You need to break your problem down into smaller pieces and then approach those pieces one at a time.

Step 1: Can you create a sketch that just shows a rectangle as you drag, but has the rectangle go away when you let go of the mouse? Start over with a basic sketch that does just this one thing, and get it working perfectly before you move on to the next step.

Step 2: Can you draw shapes to an off-screen buffer? It looks like you've tried this in your current code, but note that you never actually draw any shapes to your buffer, and you never actually draw your buffer to the screen. Again, start with a basic sketch that just does this. Don't even worry about user input or anything yet, just get a hard-coded rectangle drawn to an off-screen buffer, then draw that off-screen buffer to the screen.

Step 3: Can you combine those two to show the rectangle when you're drawing it, then draw it to the off-screen buffer when the user lets go?

Step 4: Only when you have the rectangle working perfectly, then move on to other shapes.

This is how programming works: you have to break your problem down into small steps like this, and then you have to approach each step in isolation. If you get stuck, you can come back with an MCVE showing just one of these steps, and we'll go from there. Good luck.

Upvotes: 0

Related Questions