Array Of Buttons

edited May 2015 in How To...

I am trying to create an array of buttons which has an integer associated with each button. Then, when a single button is clicked, this value is sent to an Arduino. I left out the serial communication part of the code. I know how to handle that portion. What I am stuck on is coming up with a simple way to associate integers 0-9 with buttons 0-9.

I know I can simply write out a brute force version of the code to associate each element of my array of buttons with a specific interger but I'd like to know how to write this simply, maybe using iteration.

Here is the code I have so far. I commented out the bit of code which I tried. I feel like its on the right track, but missing something crucial. I'm still fairly new to Processing and coding in general.

I'm using the button class from one of the examples in Processing. Not sure which one.

int unit = 40;
int count;
int num;
int butVal;
Button[] buts;


void setup() {
  size(400, 200);
  colorMode(RGB);
  int wide = width/unit;
  count = wide;
  buts = new Button[count];

  int index = 0;
  for (int x = 0; x < wide; x++) {
    buts[index++] = new Button(x*unit, 50, 25, color(255, 0, 0), color(0, 255, 0), color(0, 0, 255));
  }
}

void draw() {
  background(0, 0, 0);
  for (Button but : buts) {
    but.update();
    but.display();
/*   
 for (int v = 0; v <= buts.length; v++) {
      butVal[v] = v;
      if (but.pressed)println(butVal[v]);

    }
*/

  }
  for ( int t = 0; t <= 10; t ++) {
    num = t;
    fill(0, 255, 0);
    text(num, 40*t, 40);
  }
}

void mousePressed() {
  for (Button but : buts) {
    but.press();
  }
}

void mouseReleased() {
  for (Button but : buts) {
    but.release();
  }
}



//_____________________________//

class Button {
  int x, y; // The x- and y-coordinates
  int size; // Dimension (width and height)
  color baseGray; // Default gray value
  color overGray; // Value when mouse is over the button
  color pressGray; // Value when mouse is over and pressed
  boolean over = false; // True when the mouse is over
  boolean pressed = false; // True when the mouse is over and pressed

  Button(int xp, int yp, int s, color b, color o, color p) {
    x = xp;
    y = yp;
    size = s;
    baseGray = b;
    overGray = o;
    pressGray = p;
  }

  // Updates the over field every frame
  void update() {
    if ((mouseX >= x) && (mouseX <= x + size) &&
      (mouseY >= y) && (mouseY <= y + size)) {
      over = true;
    } else {
      over = false;
    }
  }

  boolean press() {
    if (over == true) {
      pressed = true;
      return true;
    } else {
      return false;
    }
  }

  void release() {
    pressed = false; // Set to false when the mouse is released
  }

  void display() {
    if (pressed == true) {
      fill(pressGray);
    } else if (over == true) {
      fill(overGray);
    } else {
      fill(baseGray);
    }
    stroke(255);
    rect(x, y, size, size);
  }
}

Answers

  • Please, see How to format code and text and edit your message to improve it. Thanks.

  • edited May 2015

    Please, see How to format code and text and edit your message to improve it. Thanks.

    Now much easier to read!

  • edited May 2015 Answer ✓

    Cool. Meanwhile, I was looking at your code. The loop is OK. The value of v when but.pressed is true is the value you are looking for: you can stop the loop (break) and use this value.

  • Cool. Meanwhile, I was looking at your code. The loop is OK. The value of v is but.pressed is true is the value you are looking for: you can stop the loop (break) and use this value.

    Sorry but can you explain what you mean a little more?

    Are you saying write a few statements in the loop saying something along the lines of this pseudo-code:

    if (but.pressed)println(butVal[v]);
    switch(v) {
    case 1:
    prinln("1");
    break;
    
    case 2:
    println("2");
    break;
    
    etc......
    }
    
  •  for (int v = 0; v <= buts.length; v++) {
          butVal[v] = v;
          if (but.pressed) {
            doSomethingWith(v);
            break; // Other buttons won't be pressed, just stop
          }
     }
    
  • Answer ✓

    demonstrate how to use this to start different sub sketches inside the sketch:

    // states -------------------------------
    // consts
    final int normal = 0;
    final int program0 = 1;
    final int program1 = 2;
    final int program2 = 3;
    int state = normal; // var: current  
    
    // buttons --------------------------
    int count;
    Button[] buts;
    
    // Misc for programs ------------------------------ 
    float rotateValue=0.0; // for Box, left segment
    PVector helpPoint=new PVector();     // for Line etc., left segment, Point #1
    PVector helpPoint2=new PVector();             // Point #2
    PVector helpPointAdd;           // vector for moving Point #1
    PVector helpPoint2Add;          // vector for moving Point #2
    
    //-------------------------------------------------
    // the core functions 
    
    void setup() {
      size(400, 200);
      // colorMode(RGB);
      int unit = 40;
      // int wide = width/unit;
      int count = 3;
      buts = new Button[count];
    
      for (int x = 0; x < count; x++) {
        buts[x] = new Button(x*unit+66, 150, 25, 
        color(255, 0, 0), color(0, 255, 0), color(0, 0, 255), 
        x);
      }
    }
    
    void draw() {
      background(0, 0, 0);
      if (state==normal) {
        text("Please select one sketch to show", 17, 17);
        for (Button but : buts) {
          but.update();
          but.display();
        }
      } else if (state==program0) {
        draw0();
      } else if (state==program1) {
        draw1();
      } else if (state==program2) {
        draw2();
      } else {
        println ("Unknown state (error #965)");
      }
    }
    
    //-------------------------------------------------
    // Inputs 
    
    void mousePressed() {
      if (state==program0 || state==program1 || state==program2) {
        // go back to normal 
        state = normal;
      } else if (state==normal ) {
        for (Button but : buts) {
          but.press();
          if (but.pressed) {
            evalButton(but); 
            break; // Other buttons won't be pressed, just stop
          } // if
        } // for
      } // else if
      else {
        println ("Unknown state (error #1065)");
      }
    } // func 
    
    void evalButton(Button but) {
      println(but.index);
      if (but.index==0) { 
        setup0(); 
        state=program0;
      } else if (but.index==1) { 
        setup1(); 
        state=program1;
      } else if (but.index==2) { 
        setup2(); 
        state=program2;
      } else {
        println ("Unknown button index (error #1165)");
      }
    } // func 
    
    void mouseReleased() {
      for (Button but : buts) {
        but.release();
      }
    }
    
    void keyPressed() {
      state=normal; // return to normal state 
      key=0; // kill escape
    }
    
    // --------------------------------------------
    // the sub-sketches we want to start 
    
    void setup0() {
      initPointsForLine();
    }
    
    void draw0() {
      stroke(0, 255, 0);
      line (helpPoint.x, helpPoint.y, 
      helpPoint2.x, helpPoint2.y );
      checkHelpPointsForLine();
    }
    
    // ---
    
    void setup1() {
      initPointsForLine();
    }
    
    void draw1() {
      stroke(0, 255, 0);
      ellipse (helpPoint.x, helpPoint.y, 10, 10);
      ellipse (helpPoint2.x, helpPoint2.y, 10, 10 );
      checkHelpPointsForLine();
    }
    
    // ---
    
    void setup2() {
      initPointsForLine();
    }
    
    void draw2() {
      stroke(0, 255, 0);
      rect (helpPoint.x, helpPoint.y, 
      helpPoint2.x-helpPoint.x, helpPoint2.y-helpPoint.y );
      checkHelpPointsForLine();
    }
    
    // ----------------------------------------------
    // help funcs for the sub-functions 
    
    void initPointsForLine() {
      // invisible help lines on the left side leading to green line 
      helpPoint = new PVector(random(width), random(height));
      helpPoint2 = new PVector(random(width), random(height));
      helpPointAdd = new PVector(random(-2, 2), random(-2, 2));
      helpPoint2Add = new PVector(random(-2, 2), random(-2, 2));
    }
    
    void checkHelpPointsForLine() {
      // lines on the left side leading to green line on page 1
      helpPoint.add(helpPointAdd);
      helpPoint2.add(helpPoint2Add);
    
      // check helpPoint ----------------------------
      helpPointAdd.x = keepInBoundary(helpPoint.x, 12, width-13, helpPointAdd.x);
      helpPointAdd.y = keepInBoundary(helpPoint.y, 13, height -13, helpPointAdd.y);
      // check helpPoint2 ----------------------------
      helpPoint2Add.x = keepInBoundary(helpPoint2.x, 12, width-13, helpPoint2Add.x);  
      helpPoint2Add.y = keepInBoundary(helpPoint2.y, 13, height -13, helpPoint2Add.y);
    } // func 
    
    float keepInBoundary(float testPoint, float lowerBoundary, float upperBoundary, float valueToAdd) {
      // Situation: testPoint is a ball position and valueToAdd gets added to it, so testPoint flies. 
      // Now testPoint must stay within lowerBoundary and upperBoundary (e.g. screen). 
      // ValueToAdd gets changed accordingly and is returned as return value.
      if (testPoint<lowerBoundary) {
        valueToAdd=abs(valueToAdd);
      }
      if (testPoint>upperBoundary) {
        valueToAdd=-1*abs(valueToAdd);
      } 
      return valueToAdd;
    } // func 
    
    
    //_____________________________//
    
    class Button {
    
      int x, y; // The x- and y-coordinates
      int size; // Dimension (width and height)
      color baseGray; // Default gray value
      color overGray; // Value when mouse is over the button
      color pressGray; // Value when mouse is over and pressed
      boolean over = false; // True when the mouse is over
      boolean pressed = false; // True when the mouse is over and pressed
      int index;
    
      Button(int xp, int yp, 
      int s, 
      color b, 
      color o, 
      color p, 
      int index_) {
        x = xp;
        y = yp;
        size = s;
        baseGray = b;
        overGray = o;
        pressGray = p;
        index=index_;
      }
    
      // Updates the over field every frame
      void update() {
        if ((mouseX >= x) && (mouseX <= x + size) &&
          (mouseY >= y) && (mouseY <= y + size)) {
          over = true;
        } else {
          over = false;
        }
      }
    
      boolean press() {
        if (over == true) {
          pressed = true;
          return true;
        } else {
          pressed = false;
          return false;
        }
      }
    
      void release() {
        // Set to false when the mouse is released
        pressed = false;
      }
    
      void display() {
        if (pressed == true) {
          fill(pressGray);
        } else if (over == true) {
          fill(overGray);
        } else {
          fill(baseGray);
        }
        // rect 
        stroke(255);
        rect(x, y, size, size);
        // text above 
        fill(0, 255, 0);
        text(index, x+12, y-11);
      }
    }
    // ===============================================
    
  • demonstrate how to use this to start different sub sketches inside the sketch:

    Wow. This is great. A little overkill for my purposes but definitely something I could use. I can simply associate each state with an integer value. Then when that state is active, the integer value can be added to a string which then can be sent to the Arduino.

    The function part is what always gets me. I'm still getting the hang of calling functions and creating classes.

    Know of any good literature I can pick up? I'm reading Nature of Code right now.

  • Answer ✓

    Nature of Code is very good

  • Thanks Chrisir. What you posted was a huge help. My code is looking great now.

Sign In or Register to comment.