Trouble detecting the right position of the mouse for list of buttons

Hey guys,

I’m fairly new to processing but i’m just starting to get the hang of it. I’ve been working on a program in which I can click checkboxes which results in a building up score.
when trying to make the checkboxes themselves scalable for different screen sizes, I changed how the rectangles are drawn. Ofcourse I also have to update the clickable area for the checkboxes, but i’m having so much trouble figuring out what is wrong about it. Could anyone help me with this?

now I know I have a lot of extra’s that aren’t needed at all: I did this because for my school project, I need to include a lot of elements. that is why I added all of those extras. just ignore them for now haha.
my code is below here:

void setup(){
  surface.setResizable(true);
  fullScreen();
  //size(1000,650);
  textSize(height/50);
  smooth();
  frameRate(60);
  final String[] SCORES = loadStrings("scoreData.txt");
  if (SCORES!=null) score=int(SCORES[0]);
  final String STATES[] = loadStrings("statesData.txt");
  if (STATES!=null) ID[i]=int(STATES[0]);
  for(i=0;i<names.length;i++){
  if (STATES!=null) ID[i]=int(STATES[i]);
  }
}


String[] names={"deadline","ZIP-formaat","storyboard","schets","flowchart","punt","lijn","driehoek","vierhoek","rechthoek",
  "ellipse","tekst","grijswaarde","RGB","HEX","alpha","kleur-variabele","mouseX","mouseY","frame???","background refresh",
  "int","float","color","boolean","char","string","systeemvariabele","eigen variabele","system final","eigen final","local",
  "global","toewijzing","rekenkundig","rekenkundige toewijzing???","logisch","if","if-else","if-else-if","for-loop",
  "while-loop","tekenfuncties","setup","draw","eigen void-functie","eigen type-functie","parameters","declaratie lege array",
  "declaratie gevulde array",".length","array toepassen in animatie","mouseX","mouseY","mousePressed","mouseButton","Clicked",
  "dragged","moved","pressed","released","wheel","key","keyCode","keyPressed","pressed","released","inspringing correct",
  "declaraties","setup","draw","functies","samenhang???","Complexe animatie","Compleet begrip opdracht",
  "gevorderden-lesmateriaal","classes","non-lesstof materiaal"};

float[] weights={1,1,1,1,1, 0.71,0.71,0.72,0.72,0.72,0.71,0.71, 1,1,1,1,1, 1.25,1.25,1.25,1.25, 0.83,0.83,0.83,0.83,0.83,0.83, 
  0.83,0.83,0.83,0.83,0.83,0.83, 1.25,1.25,1.25,1.25, 1.67,1.66,1.67, 2.5,2.5, 0.83,0.83,0.83,0.83,0.83,0.83, 
  1.25,1.25,1.25,1.25, 1.25,1.25,1.25,1.25, 0.83,0.83,0.83,0.83,0.83,0.83, 1.67,1.66,1.67, 2.5,2.5, 
  0.83,0.83,0.83,0.83,0.83,0.83, 10, 10, 3.33,3.34,3.33};

float score;

int padding;
int xCheck = padding;
float ySpacing;
float yCheck;
int rCheck;

int mouseAlpha;

Boolean Pressed = false;

char infoKey = 'i';
Boolean infopanel = false;
int infoItems=4;
int sInfo;
int infoTS = 10;

int i;

String symbol;

float e,d;

float scroll;

color CM = 255;

String notification="";
int notiAlpha;

void draw(){
  background(#83E7F0);
  
  noStroke();
  fill(#66D37F);
  triangle(width+100,height,width/2,height,width/1.2,height/2);
  fill(#4EB765);
  triangle(width,height,0,height,width/2,height/4);
  fill(#F7F2D7);
  quad(width/2,height/4,width/1.9,height,width/1.1,height,width/1.96,height/3.77);
  fill(#59D175);
  triangle(-50,height,width/2,height,width/3.5,height/1.5);
  
  fill(255-CM);
  stroke(0);
  textAlign(CENTER);
  text(notification,width/2,padding*2);
  stroke(255-CM,notiAlpha);
  strokeWeight(2);
  line(width/2-20,padding*3,width/2+20,padding*3);
  textAlign(CORNER);
  text("THE PATH TO THE PERFECT SCORE",padding,padding*2+scroll);
  textSize(width/65+10);
  text("Score:",width/1.19,height/2.1);
  textSize(width/80+10);
  text(score,width/1.2,height/1.9);
  
  infoTS=10+width/50;
  
  if(infopanel==true){
    sInfo = (infoItems+1)*infoTS;
    fill(255-CM,100);
    noStroke();
    rectMode(CORNERS);
    rect(width-padding,padding,width/1.5,sInfo,width/60);
    fill(CM);
    textSize(infoTS/2);
    text("Information",width/3*2+padding/2,padding*2);
    text("Press ' s ' to save",width/3*2+padding,2.5*infoTS);
    text("Press ' R ' to reset",width/3*2+padding,3*infoTS);
    text("Click ' RMB ' to toggle dark mode",width/3*2+padding,3.5*infoTS);
    
    
    text("Press ' "+infoKey+" ' to close infopanel",width/3*2+padding,sInfo-infoTS/2);
  } else{
    textSize(infoTS/2);
    textAlign(RIGHT);
    text("Press ' "+infoKey+" ' to open infopanel",width-padding,padding*2);
  }
  textSize(height/80+5);
  for(i=0; i<names.length; i++){
    for(i=0; i<names.length; i++){
      checkBox(i+2,names[i],weights[i]);
    }
  }
  textSize(height/50);
  if(notification!=""){
    notiAlpha=255;
  }
    
  stroke(255-CM,200);
  strokeWeight(width/140);
  point(mouseX,mouseY);
  stroke(255-CM,mouseAlpha);
  strokeWeight(2);
  noFill();
  ellipse(mouseX,mouseY,rCheck,rCheck);
  strokeWeight(0);

}
void mouseDragged(MouseEvent event){
  float dy = mouseY - pmouseY;
  scroll-=-dy;
}

void mouseWheel(MouseEvent event){
  e = event.getCount();
  scroll+=-e*20;
}

int[] ID = new int[100];

void checkBox(int i,String nItem,float scoreAmount){
  int r=50; int g=50; int b=50;
  rCheck = width/50;
  padding = width/50;
  fill(255-CM);
  textAlign(CORNER,CENTER);
  text(nItem,padding*1.5+rCheck,(rCheck/2+padding)*i+scroll);
  if (mouseX>=padding && mouseX<=padding+rCheck && mouseY>=(padding)*i && mouseY<=(padding+(rCheck))*i){
    if(mouseButton==LEFT){
      if(mousePressed == true && Pressed == false){
        Pressed = true;
        if (ID[i] == 0) {
          ID[i]+=1;
          score+=scoreAmount;
          println("ID"+ i +':'+ ID[i]);       
        } else {
          ID[i] = 0;
          score-=scoreAmount;
          println("ID"+ i +':'+ ID[i]);
        }
      }
      if(mousePressed !=true){
         Pressed = false;
      }
    }
  }
  if (ID[i]==0){
    symbol = "V";
    r=250; g=50; b=50;
  }
  else if (ID[i] != 0){
    symbol = "X";
    r=89; g=209; b=117;
  }  
  stroke(255-CM);
  strokeWeight(1);
  fill(r,g,b);
  rectMode(CENTER);
  rect(padding+rCheck/2,(rCheck/2+padding)*i,rCheck,rCheck);
  fill(255-CM);
  textAlign(CENTER,CENTER);
  text(symbol,padding+rCheck/2,(rCheck/2+padding)*i+scroll);
}

String[] states = new String[names.length];
void keyPressed(){
  if(key=='s'){
    
    for(i=0; i<names.length; i++){
      states[i] = str(ID[i]);
    }
    saveStrings(dataPath("statesData.txt"), states);
    saveStrings(dataPath("scoreData.txt"), new String[]{str(score)});
    println("Score:"+score);
    println("Saved");
    notification = "Saved";
  }
  if(keyCode==82){//R
    for(i=0;i<=names.length;i++){
      ID[i]=0;
    }
    score=0;
    println("reset");
    notification = "Reset";
  }
  if(key==infoKey&& infopanel==false){
    infopanel=true;
  } else if(key=='i'&& infopanel==true){
    infopanel=false;
  }
}

void mousePressed(){
  mouseAlpha=200;
}

void mouseReleased(){
  mouseAlpha=0;
}

void mouseClicked(){
  if(mouseButton==RIGHT){
    if(CM==255){
      CM=0;
      println("Dark mode disabled");
      notification = "Dark mode disabled";
    }
    else if(CM==0){
      CM=255;
      println("Dark mode enabled");
      notification = "Dark mode enabled";
    }
  }
}
void keyReleased(){
  if(key=='1'){
    surface.setSize(900,600);
    println("check");
  }
  if(key=='2'){
    surface.setSize(1366,768);
  }
  if(key=='3'){
    surface.setSize(1920,1080);
  }
}
1 Like

Maybe this is the line that is troubling you?

In my experience: since you use rectmode Center, the position for the buttons is its center. NOT the upper left corner.

So your if must be something like

mouseX>position-buttonWidth/2 etc. !!!

1 Like

Hi! thanks for your response!
yes you’re right, that’s the line that needs changing and indeed I got in trouble because of rectmode CENTER.
However, I have already tried your tip with a lot of different values and calculations, but I just can’t seem to find the right one…
I’m hoping for someone to figure out what the right code for that line should be so that the area of the box is right, and the spacing between each box is also right.
the only bit that needs changing is this:

mouseY>=(padding)*i && mouseY<=(padding+(rCheck))*i

that is because the X values are already correct.
Could anyone figure out what these values should become?

Also for y the Center property applies.

Hence it should be

mouseY>=(padding)*i - (buttonHeight/2) && 
mouseY<=(padding+(rCheck))*i + (buttonHeight/2) ) { ...

I have tried out your code, but there is something not right.
the first box is clickable above the upper end of the rendered rect and below the lower end.
if you continue to click boxes further down the list, clicking on for example the place where you see box 11, box 8 is toggled. This is a problem i’ve had before and I was unable to fix it.
it might help to look at how the box is drawn:

  rCheck = width/50;
  padding = width/50;
rect(padding+rCheck/2,(rCheck/2+padding)*i,rCheck,rCheck);

function checkBox seems to be relevant here.

But I don’t understand why you call it like this:

  for (i=0; i<names.length; i++) {  // WHY NESTED FOR-LOOP
    for (i=0; i<names.length; i++) {
      checkBox(i+2, names[i], weights[i]);  //  HERE i+2  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    }
  }

why not like this:

  for (i=0; i<names.length; i++) {
      checkBox(i, names[i], weights[i]);   //  HERE ONLY i   !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  }

this version works for the rects



void setup() {
  surface.setResizable(true);
  fullScreen();
  //size(1000,650);
  textSize(height/50);
  smooth();
  frameRate(60);
  final String[] SCORES = loadStrings("scoreData.txt");

  if (SCORES!=null)
    score=int(SCORES[0]);

  final String STATES[] = loadStrings("statesData.txt");

  if (STATES!=null) 
    ID[i]=int(STATES[0]);

  for (i=0; i<names.length; i++) {
    if (STATES!=null) ID[i]=int(STATES[i]);
  }
}


String[] names={"deadline", "ZIP-formaat", "storyboard", "schets", "flowchart", "punt", "lijn", "driehoek", "vierhoek", "rechthoek", 
  "ellipse", "tekst", "grijswaarde", "RGB", "HEX", "alpha", "kleur-variabele", "mouseX", "mouseY", "frame???", "background refresh", 
  "int", "float", "color", "boolean", "char", "string", "systeemvariabele", "eigen variabele", "system final", "eigen final", "local", 
  "global", "toewijzing", "rekenkundig", "rekenkundige toewijzing???", "logisch", "if", "if-else", "if-else-if", "for-loop", 
  "while-loop", "tekenfuncties", "setup", "draw", "eigen void-functie", "eigen type-functie", "parameters", "declaratie lege array", 
  "declaratie gevulde array", ".length", "array toepassen in animatie", "mouseX", "mouseY", "mousePressed", "mouseButton", "Clicked", 
  "dragged", "moved", "pressed", "released", "wheel", "key", "keyCode", "keyPressed", "pressed", "released", "inspringing correct", 
  "declaraties", "setup", "draw", "functies", "samenhang???", "Complexe animatie", "Compleet begrip opdracht", 
  "gevorderden-lesmateriaal", "classes", "non-lesstof materiaal"};

float[] weights={1, 1, 1, 1, 1, 0.71, 0.71, 0.72, 0.72, 0.72, 0.71, 0.71, 1, 1, 1, 1, 1, 1.25, 1.25, 1.25, 1.25, 0.83, 0.83, 0.83, 0.83, 0.83, 0.83, 
  0.83, 0.83, 0.83, 0.83, 0.83, 0.83, 1.25, 1.25, 1.25, 1.25, 1.67, 1.66, 1.67, 2.5, 2.5, 0.83, 0.83, 0.83, 0.83, 0.83, 0.83, 
  1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 1.25, 0.83, 0.83, 0.83, 0.83, 0.83, 0.83, 1.67, 1.66, 1.67, 2.5, 2.5, 
  0.83, 0.83, 0.83, 0.83, 0.83, 0.83, 10, 10, 3.33, 3.34, 3.33};

float score;

int padding;
int xCheck = padding;
float ySpacing;
float yCheck;
int rCheck;

int mouseAlpha;

Boolean Pressed = false;

char infoKey = 'i';
Boolean infopanel = false;
int infoItems=4;
int sInfo;
int infoTS = 10;

int i;

String symbol;

float e, d;

float scroll;

color CM = 255;

String notification="";
int notiAlpha;

void draw() {
  background(#83E7F0);

  noStroke();
  fill(#66D37F);
  triangle(width+100, height, width/2, height, width/1.2, height/2);
  fill(#4EB765);
  triangle(width, height, 0, height, width/2, height/4);
  fill(#F7F2D7);
  quad(width/2, height/4, width/1.9, height, width/1.1, height, width/1.96, height/3.77);
  fill(#59D175);
  triangle(-50, height, width/2, height, width/3.5, height/1.5);

  fill(255-CM);
  stroke(0);
  textAlign(CENTER);
  text(notification, width/2, padding*2);
  stroke(255-CM, notiAlpha);
  strokeWeight(2);
  line(width/2-20, padding*3, width/2+20, padding*3);
  textAlign(CORNER);
  text("THE PATH TO THE PERFECT SCORE", padding, padding*2+scroll);
  textSize(width/65+10);
  text("Score:", width/1.19, height/2.1);
  textSize(width/80+10);
  text(score, width/1.2, height/1.9);

  infoTS=10+width/50;

  if (infopanel==true) {
    sInfo = (infoItems+1)*infoTS;
    fill(255-CM, 100);
    noStroke();
    rectMode(CORNERS);
    rect(width-padding, padding, width/1.5, sInfo, width/60);
    fill(CM);
    textSize(infoTS/2);
    text("Information", width/3*2+padding/2, padding*2);
    text("Press ' s ' to save", width/3*2+padding, 2.5*infoTS);
    text("Press ' R ' to reset", width/3*2+padding, 3*infoTS);
    text("Click ' RMB ' to toggle dark mode", width/3*2+padding, 3.5*infoTS);


    text("Press ' "+infoKey+" ' to close infopanel", width/3*2+padding, sInfo-infoTS/2);
  } else {
    textSize(infoTS/2);
    textAlign(RIGHT);
    text("Press ' "+infoKey+" ' to open infopanel", width-padding, padding*2);
  }
  textSize(height/80+5);
  for (i=0; i<names.length; i++) {
    //  for (i=0; i<names.length; i++) {
    checkBox(i, names[i], weights[i]);
    //  }
  }
  textSize(height/50);
  if (notification!="") {
    notiAlpha=255;
  }

  stroke(255-CM, 200);
  strokeWeight(width/140);
  point(mouseX, mouseY);
  stroke(255-CM, mouseAlpha);
  strokeWeight(2);
  noFill();
  ellipse(mouseX, mouseY, rCheck, rCheck);
  strokeWeight(0);
}
void mouseDragged(MouseEvent event) {
  float dy = mouseY - pmouseY;
  scroll-=-dy;
}

void mouseWheel(MouseEvent event) {
  e = event.getCount();
  scroll+=-e*20;
}

int[] ID = new int[100];

void checkBox(int i, String nItem, float scoreAmount) {
  int r=50; 
  int g=50; 
  int b=50;
  rCheck = width/50;
  padding = width/50;
  fill(255-CM);
  textAlign(CORNER, CENTER);
  text(nItem, padding*1.5+rCheck, (rCheck/2+padding)*i+scroll);

  if (mouseX>=padding && 
    mouseX<=padding+rCheck && 
    mouseY>=((rCheck/2+padding)*i)  - (rCheck/2) && 
    mouseY<=((rCheck/2+padding)*i)  + (rCheck/2) 
    ) {
    //
    if (mouseButton==LEFT) {
      if (mousePressed == true && Pressed == false) {
        Pressed = true;
        if (ID[i] == 0) {
          ID[i]+=1;
          score+=scoreAmount;
          println("ID"+ i +':'+ ID[i]);
        } else {
          ID[i] = 0;
          score-=scoreAmount;
          println("ID"+ i +':'+ ID[i]);
        }
      }
      if (mousePressed !=true) {
        Pressed = false;
      }
    }
  }
  if (ID[i]==0) {
    symbol = "V";
    r=250; 
    g=50; 
    b=50;
  } else if (ID[i] != 0) {
    symbol = "X";
    r=89; 
    g=209; 
    b=117;
  }  
  stroke(255-CM);
  strokeWeight(1);
  fill(r, g, b);
  rectMode(CENTER);
  rect(padding+rCheck/2, (rCheck/2+padding)*i, rCheck, rCheck);
  fill(255-CM);
  textAlign(CENTER, CENTER);
  text(symbol, padding+rCheck/2, (rCheck/2+padding)*i+scroll);
}


String[] states = new String[names.length];

void keyPressed() {
  if (key=='s') {

    for (i=0; i<names.length; i++) {
      states[i] = str(ID[i]);
    }
    saveStrings(dataPath("statesData.txt"), states);
    saveStrings(dataPath("scoreData.txt"), new String[]{str(score)});
    println("Score:"+score);
    println("Saved");
    notification = "Saved";
  }
  if (keyCode==82) {//R
    for (i=0; i<=names.length; i++) {
      ID[i]=0;
    }
    score=0;
    println("reset");
    notification = "Reset";
  }
  if (key==infoKey&& infopanel==false) {
    infopanel=true;
  } else if (key=='i'&& infopanel==true) {
    infopanel=false;
  }
}

void mousePressed() {
  mouseAlpha=200;
}

void mouseReleased() {
  mouseAlpha=0;
}

void mouseClicked() {
  if (mouseButton==RIGHT) {
    if (CM==255) {
      CM=0;
      println("Dark mode disabled");
      notification = "Dark mode disabled";
    } else if (CM==0) {
      CM=255;
      println("Dark mode enabled");
      notification = "Dark mode enabled";
    }
  }
}
void keyReleased() {
  if (key=='1') {
    surface.setSize(900, 600);
    println("check");
  }
  if (key=='2') {
    surface.setSize(1366, 768);
  }
  if (key=='3') {
    surface.setSize(1920, 1080);
  }
}
//
1 Like

haah you’re right, that nested loop was completely redundant!
why I did +2 is because it functions to only start drawing boxes from a lower starting point. without it, the first boxes’ position would be halfway through the title.
And thanks for the working code! I’m really happy with your help :smile:

2 Likes