Processing Starter Article 8

Mouse Interaction

Respond to mouse position, clicks, and drags using Processing's built-in variables and event functions to build interactive sketches.

⏱ 13 min processing mouse interaction events input

Mouse Variables

Processing automatically tracks the mouse and makes its position available through built-in variables that update every frame:

Variable Type What it holds
mouseX int Current mouse x position
mouseY int Current mouse y position
pmouseX int Mouse x position in the previous frame
pmouseY int Mouse y position in the previous frame
mousePressed boolean True while any mouse button is held down
mouseButton int Which button: LEFT, RIGHT, or CENTER

You’ve already seen mouseX and mouseY. The others open up more interaction patterns.

pmouseX and pmouseY

pmouseX and pmouseY hold the mouse position from the previous frame. The difference between current and previous position gives you the mouse’s velocity — how fast and in which direction it’s moving:

void draw() {
  float speed = dist(mouseX, mouseY, pmouseX, pmouseY);
  println("Mouse speed: " + speed + " px/frame");
}

A common use: drawing smooth strokes by connecting current and previous positions with a line:

void setup() {
  size(600, 400);
  background(250);
  stroke(30);
  strokeWeight(3);
}

void draw() {
  if (mousePressed) {
    line(pmouseX, pmouseY, mouseX, mouseY);
  }
}

Using line(pmouseX, pmouseY, mouseX, mouseY) instead of drawing a point at mouseX, mouseY produces a smooth, continuous stroke even when the mouse moves quickly — because it fills in the gap between the previous and current positions.

mousePressed Boolean

The mousePressed boolean is true at any moment when a mouse button is held down. Use it inside draw() to do something continuously while the button is held:

float x = 200;
float y = 200;
float speed = 3;

void setup() {
  size(400, 400);
}

void draw() {
  background(30);

  // Move toward mouse while button held
  if (mousePressed) {
    float angle = atan2(mouseY - y, mouseX - x);
    x += cos(angle) * speed;
    y += sin(angle) * speed;
  }

  fill(100, 200, 255);
  noStroke();
  ellipse(x, y, 40, 40);
}

Click and hold anywhere in the sketch. The circle chases your cursor.

atan2(dy, dx) returns the angle in radians from point (x, y) to point (mouseX, mouseY). Feeding that angle to cos() and sin() gives the direction vector, which you scale by speed.

Mouse Event Functions

For things that should happen once per click — not continuously while the button is held — Processing provides event functions. These are functions you define, and Processing calls them automatically at the right moment:

void mousePressed() {
  // Called once when any mouse button is first pressed
}

void mouseReleased() {
  // Called once when the mouse button is released
}

void mouseMoved() {
  // Called every frame while mouse moves with no button held
}

void mouseDragged() {
  // Called every frame while mouse moves with a button held
}

void mouseClicked() {
  // Called once after a press and release without significant movement
}

void mouseWheel(MouseEvent event) {
  float scroll = event.getCount();
  // scroll is -1 or 1 for each wheel tick
}

These functions live alongside setup() and draw() in your sketch — outside both of those functions, not inside them.

Example: Click to Add Circles

ArrayList<float[]> circles = new ArrayList<float[]>();

void setup() {
  size(600, 400);
  noStroke();
}

void draw() {
  background(25, 25, 40);

  for (float[] c : circles) {
    fill(c[2], c[3], c[4]);
    ellipse(c[0], c[1], c[5], c[5]);
  }
}

void mousePressed() {
  // Store x, y, r, g, b, diameter
  float[] newCircle = {
    mouseX,
    mouseY,
    random(100, 255),   // random red
    random(50, 200),    // random green
    random(150, 255),   // random blue
    random(20, 80)      // random diameter
  };
  circles.add(newCircle);
}

Each click adds a circle at the click position with a random color and size. The ArrayList stores all the circles so they persist and accumulate.

Checking Which Button Was Pressed

void mousePressed() {
  if (mouseButton == LEFT) {
    fill(255, 50, 50);   // red for left click
  } else if (mouseButton == RIGHT) {
    fill(50, 50, 255);   // blue for right click
  } else if (mouseButton == CENTER) {
    fill(50, 255, 50);   // green for middle click
  }
  ellipse(mouseX, mouseY, 40, 40);
}

Using dist() for Proximity

dist(x1, y1, x2, y2) calculates the distance between two points. Combined with the mouse position, it lets objects react to how close the cursor is:

void draw() {
  background(20);
  noStroke();

  int cols = 10;
  int rows = 10;
  float cellW = width / float(cols);
  float cellH = height / float(rows);

  for (int row = 0; row < rows; row++) {
    for (int col = 0; col < cols; col++) {
      float cx = col * cellW + cellW / 2;
      float cy = row * cellH + cellH / 2;

      float d = dist(mouseX, mouseY, cx, cy);
      float maxDist = 150;

      if (d < maxDist) {
        float influence = map(d, 0, maxDist, 1.0, 0.0);
        fill(255, map(influence, 0, 1, 50, 255), 50);
        float size = map(influence, 0, 1, 8, cellW * 0.8);
        ellipse(cx, cy, size, size);
      } else {
        fill(80);
        ellipse(cx, cy, 8, 8);
      }
    }
  }
}

Circles near the mouse enlarge and glow orange. The influence value goes from 0 at maxDist to 1 at the mouse position, creating a smooth falloff.

A Drawing Tool

Here’s a more complete painting application that demonstrates several mouse interaction techniques together:

int brushSize = 20;
color brushColor;
boolean erasing = false;

void setup() {
  size(700, 500);
  background(255);
  brushColor = color(30, 100, 220);
}

void draw() {
  // Draw a brush preview at the cursor
  cursor(CROSS);

  // The actual drawing only happens while dragging
}

void mouseDragged() {
  if (erasing) {
    stroke(255);
    strokeWeight(brushSize * 2);
  } else {
    stroke(brushColor);
    strokeWeight(brushSize);
  }
  strokeCap(ROUND);
  line(pmouseX, pmouseY, mouseX, mouseY);
}

void mouseWheel(MouseEvent event) {
  brushSize = constrain(brushSize - event.getCount() * 2, 2, 80);
}

void keyPressed() {
  if (key == 'e' || key == 'E') erasing = !erasing;
  if (key == ' ') background(255);  // clear canvas
  if (key == '1') brushColor = color(30, 100, 220);   // blue
  if (key == '2') brushColor = color(220, 60, 60);    // red
  if (key == '3') brushColor = color(60, 200, 100);   // green
  if (key == '4') brushColor = color(240, 200, 40);   // yellow
}

Features:

  • Drag to draw with smooth strokes (line from previous to current position)
  • Scroll wheel to change brush size
  • Press E to toggle eraser mode
  • Press 1–4 to change color
  • Press Space to clear the canvas (keyboard input is covered in the next tutorial)

cursor()

Processing provides cursor() to change the mouse cursor appearance within the sketch window:

cursor(ARROW);    // default arrow
cursor(CROSS);    // crosshair — good for drawing tools
cursor(HAND);     // hand pointer — good for clickable areas
cursor(MOVE);     // four-way arrow
cursor(TEXT);     // text insertion beam
noCursor();       // hide the cursor entirely

Hiding the cursor and drawing your own custom “cursor” shape at mouseX, mouseY in draw() is a common technique for interactive installations where you want full visual control.

In the next tutorial, you’ll add keyboard input — letting users control your sketch, toggle modes, and trigger events from the keyboard.