How to Access Class Properties in While Loop

" Maybe this is getting philosophical, but this is exactly what my code does.

(Okay, granted, exitLoop should initially be true)

  1. test() is called but exits immediately via return command. (same thing as doing the if in draw() but nicer imho)
  2. the loop is running, using the fact that draw() loops automatically (and calls test())
  3. when exitLoop is true again, test() is left immediately again"

Oh but no, this does not work. Have you tested it? It’s not philosophical, it just doesn’t work right.

I’ve spent days at this. I’d love it to work at you suggested. That in fact is the actual goal here.

Please input the code into a sketch and try it; I think you’ll see the issue…you get trapped into the loop and can’t get out, or you get into the loop and get out immediately.

Without a way to get the update to the isClicked property, there is no way to exit the loop. And with the other method, you never stay in the loop.

Well, - I could use a serial message to exit the loop, but I want the user to be able to click a button to get out of the loop.

Thank you Chrisir; maybe I’ve misunderstood your meaning but in my own testing it simply does not work as you are suggesting, wish it did.

1 Like

works here

sorry, I don’t know why our results offer.

the code that you can switch on and off with the button (click only once, release mouse, button stays blue) is this code:

  // do sth
  print(".");

Remark

test and eventHandler need to be called from draw

this works for me.

there is no while loop, just the draw loop which extends to test() (and to eventHandler())
I made no changes in the class iirc

  • you need to click the button (release mouse) to make it start
  • button is blue, it prints “…”
  • click again, it stops


Button[] buttons = new Button[5];
boolean displayed = false;
int LightGray = 209;
int DarkGray = 45;

boolean exitLoop = true;

// ------------------------------------------------------------------

void setup() {
  size(800, 600);

  AddButtons();
}

void draw() {
  background(100);

  for (int i=0; i<buttons.length; i++) {
    buttons[i].display();
  }

  EventHandler();
  test();
}

// ------------------------------------------------------------------

void AddButtons() {

  byte labelBoxWidth = 95;//95
  byte BoxHeight = 60;//60

  int xBoxLabelStart = 57;
  int yBoxLabelStart = 157;
  byte boxDistance = 75;//75

  byte xLabelStartOffset = 12;
  byte yLabelStartOffset = 42;

  byte labelFontSize = 32;
  byte sceneFontSize = 44;

  //color SelectedFill = color(38, 125, 247);//color(209, 34, 200);

  buttons[0] = new Button(xBoxLabelStart, 80, 60, 60, "1", 10, 20, sceneFontSize, true, DarkGray, LightGray);
  buttons[1] = new Button(xBoxLabelStart, yBoxLabelStart, labelBoxWidth, BoxHeight, "Tst1", xLabelStartOffset + 5, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
  buttons[2] = new Button(xBoxLabelStart, yBoxLabelStart + boxDistance, labelBoxWidth, BoxHeight, "Tst2", xLabelStartOffset - 6, yLabelStartOffset, labelFontSize - 2, false, DarkGray, LightGray);
  buttons[3] = new Button(xBoxLabelStart, yBoxLabelStart + 2 * boxDistance, labelBoxWidth, BoxHeight, "Tst3", xLabelStartOffset - 2, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
  buttons[4] = new Button(xBoxLabelStart, yBoxLabelStart + 3 * boxDistance, labelBoxWidth, BoxHeight, "Tst4", xLabelStartOffset + 4, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
}

void EventHandler() {
  if (buttons[0].isClicked) {
    // test();
    //  println("here");
    //buttons[0].isClicked =
    //  ! buttons[0].isClicked;

    exitLoop = false;
  } else exitLoop = true;
}

void test() {

  if (exitLoop)
    return;

  // do sth
  print(".");
}//func

// ================================================

class Button {

  int x; //x coordinate
  int y; //y coordinate
  int w; //button width
  int h; //button height

  int cr; //corner radius
  String label; //text on button
  PFont labelFont;//the font to use
  PFont sceneNumberFont; //the font for the scene number
  int textX;//offset for the text X value
  int textY;//offset for text Y value
  int fillUp;//fill color when button is up
  int fillOver; //fill color when button is over
  int lightGray;//stroke color
  int fontSize; //font size
  boolean sceneNumber;//is the label the scene number?
  boolean isClicked;
  boolean on;
  boolean isMouseOver;
  boolean changed;
  int ScnNumY = 46;
  int ScnNumX = 2;
  color selectedFill = color(38, 125, 247);//color(209, 34, 200);

  Button(int x_, int y_, int w_, int h_, String label_, int textX_, int textY_, int fontSize_, boolean sceneNumber_, int fillUp_, int fillOver_) {
    x = x_;
    y = y_;
    w = w_;
    h = h_;
    label = label_;
    textX = textX_;//additional offset
    textY = textY_;
    fontSize = fontSize_;
    fillUp = fillUp_;
    fillOver = fillOver_;
    lightGray = 209;
    labelFont = createFont("NotoSans-Regular-32.vlw", 14);
    sceneNumberFont = createFont("Ramabhadra-44-Basic.vlw", 14);
    sceneNumber = sceneNumber_;
    isClicked = false;
    on = false;
    isMouseOver = false;
    changed = false;
  }

  void display() {
    pushMatrix();
    translate(x, y);

    stroke(lightGray);
    strokeWeight(3);

    mouseOver();

    if (isClicked) {
      On();
    } else {
      Off();
    }

    popMatrix();
  }

  boolean isMouseOver() {
    if ((mouseX>=x) && (mouseX<=x+w) && (mouseY>=y) && (mouseY<=y+h)) {
      //MouseOver = true;
      return true;
    } else {
      //MouseOver = false;
      return false;
    }
  }//end isMouseOver

  void mouseOver() {
    if (!isMouseOver()) {
      isMouseOver = false;
    } else {
      isMouseOver = true;
    }
  }

  void On() {

    if (!sceneNumber) fill(selectedFill);
    else fill(selectedFill);

    rect(0, 0, w, h, 10);

    if (!sceneNumber) {
      fill(fillOver);
      textFont(labelFont, fontSize);
      text(label, textX, textY);
    } else {
      fill(fillOver);
      textFont(sceneNumberFont, 44);
      if (Integer.parseInt(label) < 10 )text(Integer.parseInt(label), ScnNumX + 16, ScnNumY);
      else if (Integer.parseInt(label) < 20) text(Integer.parseInt(label), ScnNumX + 4, ScnNumY);
      else text(Integer.parseInt(label), ScnNumX + 5, ScnNumY);
    }
  }//end void On

  void Off() {

    if (!isMouseOver) {
      if (!sceneNumber) fill(fillUp);
      else fill(fillOver);
    } else {
      fill(70);
    }
    rect(0, 0, w, h, 10);

    if (!sceneNumber) {
      fill(fillOver);
      textFont(labelFont, fontSize);
      text(label, textX, textY);
    } else {
      if (!isMouseOver) fill(fillUp);
      else fill(fillOver);
      textFont(sceneNumberFont, 44);
      if (Integer.parseInt(label) < 10 )text(Integer.parseInt(label), ScnNumX + 16, ScnNumY);
      else if (Integer.parseInt(label) < 20) text(Integer.parseInt(label), ScnNumX + 4, ScnNumY);
      else text(Integer.parseInt(label), ScnNumX + 5, ScnNumY);
    }
  }//end void Off
}//end class

void mouseReleased() {
  int i = 0;
  int buttonClicked = 0;

  //figure out which button is currently clicked
  for ( Button buttons : buttons ) {
    if (buttons.isClicked) {
      buttonClicked = i;
    }
    i++;
  }
  //println("Button clicked is: " + buttonClicked);

  //Select the one clicked, and deselect the one that is already selected! Works a treat!!! :)
  for (int j=0; j<buttons.length; j++) {
    if (buttons[j].isMouseOver) {
      buttons[j].isClicked = !buttons[j].isClicked;
      if (buttonClicked != j) buttons[buttonClicked].isClicked = false;
      println("button " + j +": " + buttons[j].isClicked);
    }
  }
}

1 Like

Thank you kindly Chrisir.

I will test it and report back.

However, I do not want test() in the draw loop. There will be many like that, and it will be a huge mess. Cannot believe you can’t just create a void with a loop and get a property variable from a class.

I really appreciate your time.

Mike

1 Like

there is nothing wrong with calling test() and from there a lot of other functions. That’s the purpose of draw().

While has disadvantages. It halts the reaction of draw() for the mouse I think. This is about draw() works, not about the access to the class.

2 Likes

Chrisir, your changes really worked! Can’t thank you enough! You really are an incredible pillar of this community. Thanks for your patience with me.

Below is the fully updated code, now no “exitLoop” var at all, more streamlined, and handles every button.

Thanks to you many folks running across this thread may be helped to create nice toggle buttons.

All my best,

Mike

Button[] buttons = new Button[5];
boolean displayed = false;
int LightGray = 209;
int DarkGray = 45;

// ------------------------------------------------------------------

void setup() {
  size(800, 600);

  AddButtons();
  
}

void draw() {
  background(100);

  for (int i=0; i<buttons.length; i++) {
    buttons[i].display();
  }

  EventHandler();
}

// ------------------------------------------------------------------

void AddButtons() {

  byte labelBoxWidth = 95;//95
  byte BoxHeight = 60;//60

  int xBoxLabelStart = 57;
  int yBoxLabelStart = 157;
  byte boxDistance = 75;//75

  byte xLabelStartOffset = 12;
  byte yLabelStartOffset = 42;

  byte labelFontSize = 32;
  byte sceneFontSize = 44;

  //color SelectedFill = color(38, 125, 247);//color(209, 34, 200);

  buttons[0] = new Button(xBoxLabelStart, 80, 60, 60, "1", 10, 20, sceneFontSize, true, DarkGray, LightGray);
  buttons[1] = new Button(xBoxLabelStart, yBoxLabelStart, labelBoxWidth, BoxHeight, "Tst1", xLabelStartOffset + 5, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
  buttons[2] = new Button(xBoxLabelStart, yBoxLabelStart + boxDistance, labelBoxWidth, BoxHeight, "Tst2", xLabelStartOffset - 6, yLabelStartOffset, labelFontSize - 2, false, DarkGray, LightGray);
  buttons[3] = new Button(xBoxLabelStart, yBoxLabelStart + 2 * boxDistance, labelBoxWidth, BoxHeight, "Tst3", xLabelStartOffset - 2, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
  buttons[4] = new Button(xBoxLabelStart, yBoxLabelStart + 3 * boxDistance, labelBoxWidth, BoxHeight, "Tst4", xLabelStartOffset + 4, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
}

void EventHandler() {
  if (buttons[0].isClicked) {
    test0();
  }
  
  if (buttons[1].isClicked) {
    test1();
  }
  
  if (buttons[2].isClicked) {
    test2();
  }
  
  if (buttons[3].isClicked) {
    test3();
  }
  
  if (buttons[4].isClicked) {
    test4();
  } 
}

void test0() {
  if (buttons[0].isClicked) {
     print("0");
     return;
  }
}//func

void test1() {
  if (buttons[1].isClicked){
    print("1");
    return;
  }
  
}//func

void test2() {
  if (buttons[2].isClicked){
    print("2");
    return;
  }
  
}//func

void test3() {
  if (buttons[3].isClicked){
    print("3");
    return;
  }
 
}//func

void test4() {
  if (buttons[4].isClicked){
    print("4");
    return;
  }
  
}//func

// ================================================

class Button {

  int x; //x coordinate
  int y; //y coordinate
  int w; //button width
  int h; //button height

  int cr; //corner radius
  String label; //text on button
  PFont labelFont;//the font to use
  PFont sceneNumberFont; //the font for the scene number
  int textX;//offset for the text X value
  int textY;//offset for text Y value
  int fillUp;//fill color when button is up
  int fillOver; //fill color when button is over
  int lightGray;//stroke color
  int fontSize; //font size
  boolean sceneNumber;//is the label the scene number?
  boolean isClicked;
  boolean on;
  boolean isMouseOver;
  boolean changed;
  int ScnNumY = 46;
  int ScnNumX = 2;
  color selectedFill = color(38, 125, 247);//color(209, 34, 200);

  Button(int x_, int y_, int w_, int h_, String label_, int textX_, int textY_, int fontSize_, boolean sceneNumber_, int fillUp_, int fillOver_) {
    x = x_;
    y = y_;
    w = w_;
    h = h_;
    label = label_;
    textX = textX_;//additional offset
    textY = textY_;
    fontSize = fontSize_;
    fillUp = fillUp_;
    fillOver = fillOver_;
    lightGray = 209;
    labelFont = createFont("NotoSans-Regular-32.vlw", 14);
    sceneNumberFont = createFont("Ramabhadra-44-Basic.vlw", 14);
    sceneNumber = sceneNumber_;
    isClicked = false;
    on = false;
    isMouseOver = false;
    changed = false;
  }

  void display() {
    pushMatrix();
    translate(x, y);

    stroke(lightGray);
    strokeWeight(3);

    mouseOver();

    if (isClicked) {
      On();
    } else {
      Off();
    }

    popMatrix();
  }

  boolean isMouseOver() {
    if ((mouseX>=x) && (mouseX<=x+w) && (mouseY>=y) && (mouseY<=y+h)) {
      //MouseOver = true;
      return true;
    } else {
      //MouseOver = false;
      return false;
    }
  }//end isMouseOver

  void mouseOver() {
    if (!isMouseOver()) {
      isMouseOver = false;
    } else {
      isMouseOver = true;
    }
  }

  void On() {

    if (!sceneNumber) fill(selectedFill);
    else fill(selectedFill);

    rect(0, 0, w, h, 10);

    if (!sceneNumber) {
      fill(fillOver);
      textFont(labelFont, fontSize);
      text(label, textX, textY);
    } else {
      fill(fillOver);
      textFont(sceneNumberFont, 44);
      if (Integer.parseInt(label) < 10 )text(Integer.parseInt(label), ScnNumX + 16, ScnNumY);
      else if (Integer.parseInt(label) < 20) text(Integer.parseInt(label), ScnNumX + 4, ScnNumY);
      else text(Integer.parseInt(label), ScnNumX + 5, ScnNumY);
    }
  }//end void On

  void Off() {

    if (!isMouseOver) {
      if (!sceneNumber) fill(fillUp);
      else fill(fillOver);
    } else {
      fill(70);
    }
    rect(0, 0, w, h, 10);

    if (!sceneNumber) {
      fill(fillOver);
      textFont(labelFont, fontSize);
      text(label, textX, textY);
    } else {
      if (!isMouseOver) fill(fillUp);
      else fill(fillOver);
      textFont(sceneNumberFont, 44);
      if (Integer.parseInt(label) < 10 )text(Integer.parseInt(label), ScnNumX + 16, ScnNumY);
      else if (Integer.parseInt(label) < 20) text(Integer.parseInt(label), ScnNumX + 4, ScnNumY);
      else text(Integer.parseInt(label), ScnNumX + 5, ScnNumY);
    }
  }//end void Off
}//end class

void mouseReleased() {
  int i = 0;
  int buttonClicked = 0;

  //figure out which button is currently clicked
  for ( Button buttons : buttons ) {
    if (buttons.isClicked) {
      buttonClicked = i;
    }
    i++;
  }
  //println("Button clicked is: " + buttonClicked);

  //Select the one clicked, and deselect the one that is already selected! Works a treat!!! :)
  for (int j=0; j<buttons.length; j++) {
    if (buttons[j].isMouseOver) {
      buttons[j].isClicked = !buttons[j].isClicked;
      if (buttonClicked != j) buttons[buttonClicked].isClicked = false;
      println("button " + j +": " + buttons[j].isClicked);
    }
  }
}
1 Like

seems to work with thread() as well

little house cleaning required


// test a special while loop

Button[] buttons = new Button[5];

boolean displayed = false;
int LightGray = 209;
int DarkGray = 45;

boolean exitLoop = true;

boolean firstTime=true;

//----------------------------------------------------

void setup() {
  size(800, 600);

  AddButtons();
}

void draw() {
  background(100);

  for (Button btn : buttons) {
    btn.display();
  }

  // the main event handler is mouseReleased below, but we need an additional EventHandler()
  EventHandler();

  //debug
  if (exitLoop)
    text ("on ", 23, 23);
  else
    text ("off", 23, 23);

  if (buttons[0].isClicked)
    text ("on1", 123, 23);
  else
    text ("off1", 123, 23);
}

//----------------------------------------------------

void AddButtons() {

  byte labelBoxWidth = 95;//95
  byte BoxHeight = 60;//60

  int xBoxLabelStart = 57;
  int yBoxLabelStart = 157;
  byte boxDistance = 75;//75

  byte xLabelStartOffset = 12;
  byte yLabelStartOffset = 42;

  byte labelFontSize = 32;
  byte sceneFontSize = 44;

  //color SelectedFill = color(38, 125, 247);//color(209, 34, 200);

  buttons[0] = new Button(xBoxLabelStart, 80, 60, 60, "1", 10, 20, sceneFontSize, true, DarkGray, LightGray);
  buttons[1] = new Button(xBoxLabelStart, yBoxLabelStart, labelBoxWidth, BoxHeight, "Tst1", xLabelStartOffset + 5, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
  buttons[2] = new Button(xBoxLabelStart, yBoxLabelStart + boxDistance, labelBoxWidth, BoxHeight, "Tst2", xLabelStartOffset - 6, yLabelStartOffset, labelFontSize - 2, false, DarkGray, LightGray);
  buttons[3] = new Button(xBoxLabelStart, yBoxLabelStart + 2 * boxDistance, labelBoxWidth, BoxHeight, "Tst3", xLabelStartOffset - 2, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
  buttons[4] = new Button(xBoxLabelStart, yBoxLabelStart + 3 * boxDistance, labelBoxWidth, BoxHeight, "Tst4", xLabelStartOffset + 4, yLabelStartOffset, labelFontSize, false, DarkGray, LightGray);
}

void EventHandler() {
  //
  if (buttons[0].isClicked ) {
    if (firstTime) {
      firstTime=false;
      thread("test");
    }
  }

  //important
  if (buttons[0].isClicked) {
    exitLoop=false;
  } else {
    exitLoop=true;
  }
}

void test() {

  println("here");

  //important
  if (buttons[0].isClicked) {
    exitLoop=false;
  } else {
    exitLoop=true;
  }

  while (!exitLoop) {

    //important
    if (buttons[0].isClicked) {
      exitLoop=false;
    } else {
      exitLoop=true;
    }

    println("in the loop!");
  }//while

  println("out of loop!");

  // reset
  firstTime=true;
}//void changeScene

void mouseReleased() {
  int i = 0;
  int buttonClicked = 0;

  //figure out which button is currently clicked
  for ( Button buttons : buttons ) {
    if (buttons.isClicked) {
      buttonClicked = i;
    }
    i++;
  }

  //Select the one clicked, and deselect the one that is already selected! Works a treat!!! :)
  for (int j=0; j<buttons.length; j++) {
    if (buttons[j].isMouseOver) {
      buttons[j].isClicked = !buttons[j].isClicked;
      if (buttonClicked != j) buttons[buttonClicked].isClicked = false;
      println("button " + j +": " + buttons[j].isClicked);
    }
  }
}

// ================================================================================================

class Button {

  int x; //x coordinate
  int y; //y coordinate
  int w; //button width
  int h; //button height
  int cr; //corner radius
  String label; //text on button
  PFont labelFont;//the font to use
  PFont sceneNumberFont; //the font for the scene number
  int textX;//offset for the text X value
  int textY;//offset for text Y value
  int fillUp;//fill color when button is up
  int fillOver; //fill color when button is over
  int lightGray;//stroke color
  int fontSize; //font size
  boolean sceneNumber;//is the label the scene number?
  boolean isClicked;
  boolean on;
  boolean isMouseOver;
  boolean changed;
  int ScnNumY = 46;
  int ScnNumX = 2;
  color selectedFill = color(38, 125, 247);//color(209, 34, 200);

  Button(int x_, int y_, int w_, int h_, String label_, int textX_, int textY_, int fontSize_, boolean sceneNumber_, int fillUp_, int fillOver_) {
    x = x_;
    y = y_;
    w = w_;
    h = h_;
    label = label_;
    textX = textX_;//additional offset
    textY = textY_;
    fontSize = fontSize_;
    fillUp = fillUp_;
    fillOver = fillOver_;
    lightGray = 209;
    labelFont = createFont("NotoSans-Regular-32.vlw", 12);
    sceneNumberFont = createFont("Ramabhadra-44-Basic.vlw", 12);
    sceneNumber = sceneNumber_;
    isClicked = false;
    on = false;
    isMouseOver = false;
    changed = false;
  }

  void display() {
    pushMatrix();
    translate(x, y);

    stroke(lightGray);
    strokeWeight(3);

    mouseOver();

    if (isClicked) {
      On();
    } else {
      Off();
    }

    popMatrix();
  }

  boolean isMouseOver() {
    if ((mouseX>=x) && (mouseX<=x+w) && (mouseY>=y) && (mouseY<=y+h)) {
      //MouseOver = true;
      return true;
    } else {
      //MouseOver = false;
      return false;
    }
  }//end isMouseOver

  void mouseOver() {
    if (!isMouseOver()) {
      isMouseOver = false;
    } else {
      isMouseOver = true;
    }
  }

  void On() {

    if (!sceneNumber) fill(selectedFill);
    else fill(selectedFill);

    rect(0, 0, w, h, 10);

    if (!sceneNumber) {
      fill(fillOver);
      textFont(labelFont, fontSize);
      text(label, textX, textY);
    } else {
      fill(fillOver);
      textFont(sceneNumberFont, 44);
      if (Integer.parseInt(label) < 10 )text(Integer.parseInt(label), ScnNumX + 16, ScnNumY);
      else if (Integer.parseInt(label) < 20) text(Integer.parseInt(label), ScnNumX + 4, ScnNumY);
      else text(Integer.parseInt(label), ScnNumX + 5, ScnNumY);
    }
  }//end void On

  void Off() {

    if (!isMouseOver) {
      if (!sceneNumber) fill(fillUp);
      else fill(fillOver);
    } else {
      fill(70);
    }
    rect(0, 0, w, h, 10);

    if (!sceneNumber) {
      fill(fillOver);
      textFont(labelFont, fontSize);
      text(label, textX, textY);
    } else {
      if (!isMouseOver) fill(fillUp);
      else fill(fillOver);
      textFont(sceneNumberFont, 44);
      if (Integer.parseInt(label) < 10 )text(Integer.parseInt(label), ScnNumX + 16, ScnNumY);
      else if (Integer.parseInt(label) < 20) text(Integer.parseInt(label), ScnNumX + 4, ScnNumY);
      else text(Integer.parseInt(label), ScnNumX + 5, ScnNumY);
    }
  }//end void Off
}//end class
// ===

2 Likes

Chrisir, “WOW” doesn’t cover it!

Truly awesome! Thank you thank you thank you!

Now you’ve given me two alternatives - no, you’ve given US ALL two alternatives!

Thank you again!!!

Mike

1 Like