Objects to receive events

edited April 2016 in How To...

I would love to be able to create an object that would have access to the processing events, but only when the event takes place within the scope of the object. Let me put it as an example. I want to create an object (say a star). If I click on the star I want the star object to receive the mouseClick event. I would then have the option of allowing it to propagate to other objects also under the mouse icon. If have 100 stars the logic to figure out which star was clicked is a bit tedious.

Answers

  • I saw a reference to passing the PApplet around and checking for context.mousepressed. That would be great if the context was restricted to the area of the star. It still means I have to check to see is the mouse is within the bounds of my image.

  • I think it might be easier to for loop over the stars in the classical mousePressed() and pass that to the object

  • That is what I am doing, but there are a lot of other folks out there asking for this functionality. It seems like a very useful item to add to this language. As well, it is present in most other languages.

  • edited April 2016

    It is easier to implement than you might think.

    This sketch creates 10 Ball objects each one has its own event handler method. Also the draw method is registered so they draw themselves, no need to do it manually in draw() method.

    Ball[] balls = new Ball[10];
    
    int tx, ty;
    Ball selected;
    
    void setup() {
      size(600, 600);
      for (int i = 0; i < 10; i++) {
        balls[i] = new Ball();
        registerMethod("draw", balls[i]);
        registerMethod("mouseEvent", balls[i]);
      }
    }
    
    void draw() {
      background(0);
    }
    
    
    public class Ball {
      int x, y, radius, diameter;
      int fillCol, strokeCol;
    
      Ball() {
        int r, g, b;
        r = 128+(int)random(127);
        g = 128+(int)random(127);
        b = 128+(int)random(127);
        fillCol = color(r, g, b);
        strokeCol = color(r/2, g/2, b/2);
        x = 50 + (int)random(400);
        y = 50 + (int)random(400);
        diameter = 50 + (int)random(100);
        radius = diameter/2;
      }
    
      boolean isOver(int mx, int my) {
        return (mx-x)*(mx-x) + (my-y)*(my-y) < radius*radius;
      }
    
      // This method is called automatically every loop
      // becasue we have registerDraw(this object)
      void draw() {
        ellipseMode(CENTER);
        fill(fillCol);
        stroke(strokeCol);
        strokeWeight(2);
        ellipse(x, y, diameter, diameter);
      }
    
      // This method is called automatically every loop
      // becasue we have registerMouseEvent(this object)
      void mouseEvent(MouseEvent event) {
        if ((selected == null && isOver(mouseX, mouseY)) 
          || selected == this) {
          switch(event.getAction()) {
          case MouseEvent.PRESS:
            selected = this;
            break;
          case MouseEvent.DRAG:
            x = x + mouseX - pmouseX;
            y = y + mouseY - pmouseY;
            break;
          case MouseEvent.RELEASE:
            selected = null;
            break;
          }
        }
      }
    } 
    
  • Yes, that does make it easier. Why not go the next step and make it easiest?

  • Why not go the next step and make it easiest?

    What next step?

  • Addressing the proposed enhancement that I suggested. Give objects the ability to directly receive mouse events that apply to the image they represent without having to check mouseX <= ...

  • but only when the event takes place within the scope of the object

    That involves testing the mouse screen position, in other words if (mouseX >= .... Even if the shape is a PImage you would have to make sure the cursor is over the image before testing the image-pixel under the mouse position.

    The only way to avoid it is to use a colour-picking algorithm, but if the images/shapes were stacked it would only detect the topmost shape.

    I suppose it would be possible PS to provide such an enhancement or for a developer to create a contributed library for the PShape class but it is not straightforward.

    If have 100 stars the logic to figure out which star was clicked is a bit tedious.

    At least with my code you don't have that problem. :)

  • am i missing somehting obvious? where does this registerMethod comes from?

     registerMethod("draw", balls[i]);
        registerMethod("mouseEvent", balls[i]);
    
  • The registerMethod is aimed at library developers who want to hook into Processing's event handling. You can find out more here

  • thanks quark, extremely useful

Sign In or Register to comment.