Drawing program

Hello everyone,

I’m new to programming. I could use your help.
I want to create a simple interface to draw from a circle.

The problem is that I can’t draw on this circle. And I wish I could draw on it.

PImage gomme;
PImage save;
PImage delete;
PImage circle;
PFont font;
//PShape ellipse;


void setup() {
  size(768, 1024);
  background(255);
  gomme = loadImage("gomme.png");
  save = loadImage("save.png");
  delete = loadImage("delete.png");
  circle = loadImage("circle.png");
  //ellipse = loadShape("ellipse.svg");
  font = loadFont("Grotex-Regular-48.vlw");
  textFont(font);
 
} 

void draw(){
 
  image(gomme, 600, 20, 64, 74);
  image(save, 520, 20, 64, 74); 
  image(delete, 680, 20, 64, 74);
  //shape(ellipse, 300, 380, 188, 188);
  image(circle, 300, 380, 188, 188);  
  textSize(48);
  text("un soleil", 20, 60); 
  fill(210);
  
  
  
   stroke(0);
    strokeWeight(6);
  if (mousePressed == true) {
    line(mouseX, mouseY, pmouseX, pmouseY);
  }
  
  if(mousePressed){
    if(mouseX > 600 && mouseX <664){
      if (mouseY > 20 && mouseY <94){
        background(255);
      }
    }
  }

}

Solutions?

Thank you in advance

1 Like

There’s a couple of things to consider.

  1. Try changing the stroke color.
  2. mousePressed == true means the same thing as mousePressed.

If you share the images you are loading as well, I might be able to make it work.

2 Likes

You draw over the lines from the last draw cycle with your images with each new cycle of draw();

Consider:

  1. draw images once in setup and NOT in main loop of draw();
    OR once in draw() but NOT at the start of every draw() (consider this later…)
  2. draw images again with your background update with a mousePressed.
  3. Put the images in an update() method; it would be easier to call that method as required.

That will work.

:slight_smile:

I just reduced your code so I could test it.
I did not provide a solution below; I left that for you.

void setup() 
  {
  size(768, 1024, P2D);
  background(255);
  } 

void draw()
  {
  fill(210);
  stroke(0);
  strokeWeight(6);
  circle(300, 380, 188); 

  textSize(48);
  text("un soleil", 20, 60); 
  
  if (mousePressed == true) 
    {
    line(mouseX, mouseY, pmouseX, pmouseY);
    }
  
  if(mousePressed)
    {
    if(mouseX > 600 && mouseX <664)
      {
      if (mouseY > 20 && mouseY <94)
        {
        background(255);
        // Good place to add other updates
        }
      }
    }
  }  
3 Likes

Another way would be storing the lines in an ArrayList and drawing all lines from that ArrayList in every draw.

1 Like

Hey There!

Another suggestion is to use the method mousePresssed for your conditions within the if statement. But once you put it in the mouse pressed method you don’t have to have the if statements.

1 Like

I came up with a small class with buttons

The buttons

  • The delete button works,
  • the circle button works (toggle between line and circle mode)

The buttons are stored in an ArrayList buttons containing objects of type Button (from the class Button). There is a tutorial about classes and objects: https://www.processing.org/tutorials/objects/.
The buttons get an ID (0,1,2…) in the order they are created.
When evaluating the mouse in the function mousePressed() we use the ID to trigger the function exec() which executes the command for the ID (e.g. clear the canvas or set the draw mode mode to circleMode).
When using a button, the variable hold is true; in draw() we evaluate hold so we avoid drawing a line on a button in this case.

The class Button

The class Button could in theory handle images and text, since I don’t have the images I tested it only with text.
In the constructor of the class (when defineButton() would pass w and h to the constructor) you could handle resize of images img once and for all using w and h (usage of resize() once is better than using image() with 5 parameters which is doing a resize every time, very time consuming for the processor).

Chrisir


PFont font;
//PShape ellipse;

ArrayList<Button> buttons = new ArrayList();  

boolean hold=false;

// define modes 
final int lineMode = 0;
final int circleMode = 1;
//current mode
int mode = lineMode;
// names of modes
String[] stringMode={ "line", "circle (click, hold and move mouse)" };

// draw a circle variables 
boolean drawNewCircle;
PVector startCircle=new PVector(); 

void setup() {
  size(768, 1024);

  PImage gomme;
  PImage save;
  PImage delete;
  PImage circle;

  background(255);
  gomme = loadImage("gomme.png");
  save = loadImage("save.png");
  delete = loadImage("delete.png");
  circle = loadImage("circle.png");
  //ellipse = loadShape("ellipse.svg");

  // font = loadFont("Grotex-Regular-48.vlw");
  // textFont(font);

  defineButton(gomme, "gomme", 600, 20, 64, 74);
  defineButton(save, "save", 520, 20, 64, 74); 
  defineButton(delete, "delete", 680, 20, 64, 74);
  //shape(ellipse, 300, 380, 188, 188);
  defineButton(circle, "circle (on/off)", 300, 380, 188, 188);
} 

void draw() {
  textAlign(LEFT);
  fill(255); 
  noStroke(); 
  rect(0, 0, width, 30); 
  fill(0); 
  textSize(17);
  text("mode is " + stringMode[mode], 22, 22); 
  fill(210);

  for (Button b : buttons)
    b.display(); 

  textSize(48);
  text("un soleil", 20, 60); 
  fill(210);

  stroke(0);
  strokeWeight(6);
  if (!hold) {
    switch(mode) {
    case circleMode:
      // ignore
      break; 
    case lineMode:
      if (mousePressed) {
        line(mouseX, mouseY, pmouseX, pmouseY);
      }
      break;
    default:
      //Error 
      break;
    }//switch
  }//if

  if (drawNewCircle) {
    float a1 = 2 * dist (mouseX, mouseY, 
      startCircle.x, startCircle.y);
    stroke(0); 
    ellipse( startCircle.x, startCircle.y, a1, a1);
  }//if
  //
}

// -----------------------------------------------------

void mousePressed() {
  for (Button b : buttons) {
    if (b.over()) {
      exec(b.id);
      hold=true; 
      return;
    }//if
  }//for
  if (mode==circleMode) {
    startCircle.x=mouseX;
    startCircle.y=mouseY;
    drawNewCircle=true;
  }
}

void mouseReleased() {
  hold=false;
  drawNewCircle=false;
}

// -------------------------------------------------------------------

void exec(int id) {
  println(id);

  switch (id) {
  case 2:
    background(255);
    break;
  case 3:
    if (mode!=circleMode)
      mode=circleMode; 
    else 
    mode=lineMode;
    break;
  default:
    break;
  }//switch
}

void defineButton(PImage img, 
  String s, 
  float x, float y, 
  float w, float h) {
  buttons.add (new Button(img, s, x, y, buttons.size()));
}

//===================================================================

class Button {

  PImage img=null; 
  String s; 
  float x, y; 
  int id; 

  Button(PImage img_, 
    String s_, 
    float x_, float y_, 
    int id_) {
    img=img_; 
    s=s_;
    x=x_;
    y=y_;

    id=id_;
  }

  void display() {
    if (img!=null) {
      imageMode(CENTER); 
      image(img, x, y);
      return;
    }

    textAlign(CENTER);
    textSize(17);
    text(s, x, y);
    textAlign(LEFT);
  }//

  boolean over() {
    return 
      dist (mouseX, mouseY, x, y) < 30;
  }
  //
}//class
//
1 Like

Let’s try to keep this simple, guys.

3 Likes

Actually, this is a good comment… because my sketch is too complex for a beginner…

1 Like

I examined the mousePressed() function and mousePressed variable behavior and provided a couple of examples to illustrate this.

Observe console outptut:

void setup() 
  {
  size(200, 200);
  background(255, 255, 0);
  } 

void draw()
  {
  } 
  
void mousePressed()
  {
  println(frameCount, mouseButton, mousePressed);
  }

Observe console output:

void setup() 
  {
  size(200, 200);
  background(255, 255, 0);
  } 

void draw()
  {
  if (mousePressed) 
    println(frameCount, mouseButton, mousePressed);
  }

:slight_smile:

1 Like

The function mousePressed is called only once during a pressing of the mouse. That’s good for buttons.

It won’t give good results when drawing continuous lines though imo. For those the variable mousePressed is better.

1 Like

Yes those are good suggestions ! I guess I was proposing mouse pressed method because for example if OP is using the lines to build line shapes using it in draw will call multiple times on one line unnecessarily creating many instances of it. Depending on what OP requires either or can be correct !

1 Like

When filling points in an Arraylist of type PVector before adding we check if the value has changed or not

1 Like

Yes great suggestion ! In that way we wouldn’t draw over so many points.

2 Likes