How to specifically color one rect when it's hovered over?

61 views Asked by At

How does one go about coloring an individual rectangle when it's hovered over? The specific method used below really doesn't give me any ideas on how to solve this problem. It generates a grid in the window using individual rectangles. How would it be possible to listen for mouseX and mouseY and color one rectangle without disrupting this code? Thanks.

int cols,rows;
int scl = 20;
int gridsize = 0;

void setup(){
size(400,400);
int w = 400;
int h = 400;
cols = w / scl;
rows = h / scl;

}

void draw() {
//mouseX, mouseY
background(r,g,b);

for (int x = 0; x < cols; x++){
  for (int y = 0; y < rows; y++){
  stroke(55);
  //noFill();
  fill(50,50,50);
  rect(x*scl,y*scl,scl,scl);
    }
  }
}

For reference, I am using Processing 3 for Java.

3

There are 3 answers

1
George Profenza On BEST ANSWER

You can always check if the mouse is within the bounds of a rectangle:

  • you know the mouseX,mouseY values
  • you know the x,y and size of each box
  • if mouseX is within x and x+size and mouseY is within y and y+size you're over a box.

Here's the above applied to your code (if condition formatting for easy visibility, feel free to re-format):

int cols, rows;
int scl = 20;
int gridsize = 0;

void setup() {
  size(400, 400);
  int w = 400;
  int h = 400;
  cols = w / scl;
  rows = h / scl;
}

void draw() {
  //mouseX, mouseY
  background(255);

  for (int x = 0; x < cols; x++) {
    for (int y = 0; y < rows; y++) {
      int xpos = x*scl;
      int ypos = y*scl;
      stroke(55);
      if(
        (mouseX >= xpos && mouseX <= xpos+scl) &&
        (mouseY >= ypos && mouseY <= ypos+scl)
        ){
        fill(90);
      }else{
        fill(50);
      }

      rect(xpos, ypos, scl, scl);
    }
  }
}

For more info also checkout the Processing Button example

1
Kevin Workman On

George's answer is correct. I upvoted it and I believe you should mark it as the correct answer. Yushi's answer is basically just George's answer, moved into a class.

They both use point-rectangle collision detection, which checks whether the point is inside the rectangle. You just check each rectangle against the point (in your case the mouse position), and that allows you to determine which rectangle the mouse is in. This will work even if you have a bunch of rectangles of different shapes, and will even work with overlapping rectangles.

The other way to do it is using grid-based collision detection which takes advantage of the fact that you have a bunch of evenly spaced rectangles that don't overlap. You'd just use division to figure out which cell the mouse was in, and then you'd convert that cell to coordinates, and you'd use those coordinates to draw the rectangle. That might sound confusing, but it looks like this:

int cols;
int rows;
int scl = 20;

void setup() {
  size(400, 400);
  cols = width / scl;
  rows = height / scl;
}

void draw() {
  background(100);

  for (int x = 0; x < cols; x++) {
    for (int y = 0; y < rows; y++) {
      stroke(55);
      fill(50, 50, 50);
      rect(x*scl, y*scl, scl, scl);
    }
  }

  int hoveredRectColX = int(mouseX / scl);
  int hoveredRectRowY = int(mouseY / scl);
  float rectX = hoveredRectColX * scl;
  float rectY = hoveredRectRowY * scl;
  fill(255, 0, 0);
  rect(rectX, rectY, scl, scl);
}

The last block of code is the meat and potatoes. First it figures out which row and column the mouse is in, then figures out the position of that cell, and uses that to draw a rectangle. If this doesn't make sense, the best thing you can do is get out a piece of paper and a pencil and draw a bunch of examples to see the pattern of what's going on.

Shameless self-promotion: I wrote a tutorial on collision detection in Processing, including both point-rectangle and grid-based collision detection, available here.

1
Ayush Seth On

George's answer works nicely for this scenario, but there is another, a little more complex way too if might want to go Object Oriented here. For this little example, you could have a Grid class which holds and manages an array of Cell objects. Or you can just skip the Grid class and manage the Cells in your main sketch. You could give the Cell class a function to render itself and you could give each cell a color and a size too, it's totally up to you. Also, it could have a function which tells you if your mouse is over it and a function to change its color. A skeleton would look like this:

class Cell {

float x,y;
float length, breadth;
color col;

Cell(float x, float y) {
    this.x = x;
    this.y = y;

    length = 10;
    breadth = 10;
    col = color(0);
}

void render() {
    fill(col);
    rect(x, y, length, breadth);
}

void setColor(color col) {
    this.col = col;
}

boolean mouseOver() {
    if(mouseX > x && mouseX < x+length) {
        if(mouseY > y && mouseY < y+breadth) {
            return true;
        }
    }
    return false;
}

Now you could just use this class and its methods in your main sketch to find the cell with the mouse over it and call setColor on it to change its color.