G4P GUI button function

Hello everyone,
I am trying to make a software for logging data from an Arduino to a CSV file through serial communication.

I used the G4P GUI builder to create a basic GUI, and have made two buttons to start and stop the data recording by the program. The problem is I have an infinite loop in my start button program, and thus cannot stop the execution using a flag activated by the stop button as it has been disabled.

Is there a way to put a button’s programming within another button’s programming?

My code is as below.

/* =========================================================
 * ====                   WARNING                        ===
 * =========================================================
 * The code in this tab has been generated from the GUI form
 * designer and care should be taken when editing this file.
 * Only add/edit code inside the event handlers i.e. only
 * use lines between the matching comment tags. e.g.
 
 void myBtnEvents(GButton button) { //_CODE_:button1:12356:
 // It is safe to enter your event code here  
 } //_CODE_:button1:12356:
 
 * Do not rename this tab!
 * =========================================================
 */

public void button1_click1(GButton source, GEvent event) { //_CODE_:start:763894:
  String val;
  PFont fnt = createFont("Ubuntu", 16, true);
  flag = false;
  i=0;
  String[] values;
  int A=10;
  println("start - GButton >> GEvent." + event + " @ " + millis());

  ser_port.clear();
  table.addColumn("Time");
  table.addColumn("Weld No.");
  table.addColumn("Data1");
  table.addColumn("Data2");
  table.addColumn("Data3");
  table.addColumn("Data4");
  table.addColumn("Current_avg");
  table.addColumn("Current_peak");
  table.addColumn("Voltage_peak");
  table.addColumn("Voltage_avg");
  table.addColumn("Power");
  table.addColumn("Resistance");
  table.addColumn("Current_avg2");
  table.addColumn("Current_peak2");
  table.addColumn("Voltage_peak2");
  table.addColumn("Voltage_avg2");
  table.addColumn("Power2");
  table.addColumn("Resistance2");
  double start_time = millis();
  while (!flag) {
    double now = millis();
    double diff;
    val = ser_port.readStringUntil(A); //read until /n from arduino
    delay(10);
    if (val==null)
    {
      diff = now - start_time; 
    //meausre time from start of loop
      println(diff);
      if (diff > 5000) //no data for 5 seconds
      {
        flag = true; //exit loop
        fill(255, 0, 0);
        text("Data Logging stopped", 20, 280);
        textFont(fnt, 100);
      }
    }
    if (val!=null) 
    {
      values = split(val, ','); //Split string to get smaller strings with individual data
      println(val);
      println(i); //to keep count of number of welds and rows on file
      if (values[0].equals("@")) //PS Unit data
      {

        //table.addRow();
        if (values[2].equals("02")) // Schedule 2 - Negative welds
        {
          //println("I was here");

          table.setString(i, "Current_peak2", values[10]);
          table.setString(i, "Current_avg2", values[111]);
          table.setString(i, "Voltage_peak2", values[12]);
          table.setString(i, "Voltage_avg2", values[13]);
          table.setString(i, "Power2", values[14]);
          table.setString(i, "Resistance2", values[15]);
          //println("I was here 2");
        } else if (values[2].equals("01")) // Schedule 1 - Positive welds
        {
          //println("Or I was here");

          table.setString(i, "Current_peak", values[3]); 
          table.setString(i, "Current_avg", values[4]);
          table.setString(i, "Voltage_peak", values[5]);
          table.setString(i, "Voltage_avg", values[6]);
          table.setString(i, "Power", values[7]);
          table.setString(i, "Resistance", values[8]);
          //println("Or I was here 2");
        }

        //newRow.setString("Time", day()+"/"+month()+"/"+year()+" "+hour()+":"+minute()+":"+second());
      } else if (values[0].equals("$")||values[0].equals("#")) // Head controller data - Positive Welding
      {
        //TableRow newRow = table.addRow();
        table.setString(i, "Time", day()+"/"+month()+"/"+year()+" "+hour()+":"+minute()+":"+second());
        table.setString(i, "Weld No.", values[2]);
        table.setString(i, "Data1", values[3]);
        table.setString(i, "Data2", values[5]);
        table.setString(i, "Data3", values[15]);
        table.setString(i, "Data4", values[17]);
        i++;
      }
      //} else if (values[0].equals("#")) // Head controller data - Negative welding
      //{
      //  //TableRow newRow = table.addRow();
      //  table.setString(i, "Time", day()+"/"+month()+"/"+year()+" "+hour()+":"+minute()+":"+second());
      //  table.setString(i, "Weld No.", values[2]);
      //  table.setString(i, "Data1", values[3]);
      //  table.setString(i, "Data2", values[5]);
      //  table.setString(i, "Data3", values[15]);
      //  table.setString(i, "Data4", values[17]);
      //  i++;
      //}
    } 
    if (i==224)                           //count 224 instances of written data based on number of welds
    {
      flag = true;
      i=0;
    }
  }
} //_CODE_:start:763894:

public void button2_click(GButton source, GEvent event) { //_CODE_:stop:908093:
  println("stop - GButton >> GEvent." + event + " @ " + millis());
  flag = false;
  i=0;  
  saveTable(table, "welding_data/"+txt+".csv");
} //_CODE_:stop:908093:

public void textfield1_change1(GTextField source, GEvent event) { //_CODE_:filename:808476:
  println("filename - GTextField >> GEvent." + event + " @ " + millis());
  txt = filename.getText(); // get text typed in a GTextField control
} //_CODE_:filename:808476:



// Create all the GUI controls. 
// autogenerated do not edit
public void createGUI() {
  G4P.messagesEnabled(false);
  G4P.setGlobalColorScheme(GCScheme.CYAN_SCHEME);
  G4P.setMouseOverEnabled(false);
  surface.setTitle("Sketch Window");
  start = new GButton(this, 100, 104, 80, 30);
  start.setText("Start");
  start.setLocalColorScheme(GCScheme.BLUE_SCHEME);
  start.addEventHandler(this, "button1_click1");
  stop = new GButton(this, 300, 104, 80, 30);
  stop.setText("Stop");
  stop.setLocalColorScheme(GCScheme.BLUE_SCHEME);
  stop.addEventHandler(this, "button2_click");
  filename = new GTextField(this, 170, 28, 120, 30, G4P.SCROLLBARS_NONE);
  filename.setPromptText("Enter battery name");
  filename.setLocalColorScheme(GCScheme.BLUE_SCHEME);
  filename.setOpaque(true);
  filename.addEventHandler(this, "textfield1_change1");
}

// Variable declarations 
// autogenerated do not edit
GButton start; 
GButton stop; 
GTextField filename; 

1 Like

You should avoid infinite loops in single threaded applications because everything happens on the event dispatch thread so an infinite loop will make your application unresponsive to mouse and keyboard events.

The best solution is probably to read the Arduino data in a separate thread. This sketch provides an example frame work

import g4p_controls.*;

int data = 0;
boolean read_data = false;

public void setup() {
  size(400, 170, JAVA2D);
  createGUI();
  thread("readData");
}

public void draw() {
  background(230);
  valFrameCount.setText("" + frameCount);
  valTime.setText("" + millis());
  valData.setText("" + data);
}

void readData() { // read the Arduino data here
  while (true) { // create infinite loop
    while (read_data == true) {
      data++;
      // Allow time for main thread to process events
      delay(10);
    }
    // Allow time for main thread to process events
    delay(100);
  }
}

/* =========================================================
 * The following code was created by GUI Builder
 * =========================================================
 */

public void btnStartClick1(GButton source, GEvent event) { //_CODE_:btnStart:374267:
  read_data = true;
} //_CODE_:btnStart:374267:

public void btnStopClick(GButton source, GEvent event) { //_CODE_:btnStop:665304:
  read_data = false;
} //_CODE_:btnStop:665304:


// Create all the GUI controls. 
// autogenerated do not edit
public void createGUI(){
  G4P.messagesEnabled(false);
  G4P.setGlobalColorScheme(GCScheme.BLUE_SCHEME);
  G4P.setMouseOverEnabled(false);
  surface.setTitle("Sketch Window");
  lblFrameCount = new GLabel(this, 20, 10, 120, 20);
  lblFrameCount.setTextAlign(GAlign.CENTER, GAlign.MIDDLE);
  lblFrameCount.setText("Frame Count");
  lblFrameCount.setTextBold();
  lblFrameCount.setOpaque(true);
  lblTime = new GLabel(this, 20, 40, 120, 20);
  lblTime.setTextAlign(GAlign.CENTER, GAlign.MIDDLE);
  lblTime.setText("Time (ms)");
  lblTime.setTextBold();
  lblTime.setOpaque(true);
  lblData = new GLabel(this, 20, 70, 120, 20);
  lblData.setTextAlign(GAlign.CENTER, GAlign.MIDDLE);
  lblData.setText("Dummy data value");
  lblData.setTextBold();
  lblData.setOpaque(true);
  valFrameCount = new GLabel(this, 160, 10, 230, 20);
  valFrameCount.setText("0");
  valFrameCount.setOpaque(false);
  valTime = new GLabel(this, 160, 40, 230, 20);
  valTime.setText("0");
  valTime.setOpaque(false);
  valData = new GLabel(this, 160, 70, 230, 20);
  valData.setText("0");
  valData.setOpaque(false);
  btnStart = new GButton(this, 30, 100, 160, 30);
  btnStart.setText("Start");
  btnStart.setTextBold();
  btnStart.addEventHandler(this, "btnStartClick1");
  btnStop = new GButton(this, 220, 100, 160, 30);
  btnStop.setText("Stop");
  btnStop.setTextBold();
  btnStop.addEventHandler(this, "btnStopClick");
}

// Variable declarations 
// autogenerated do not edit
GLabel lblFrameCount; 
GLabel lblTime; 
GLabel lblData; 
GLabel valFrameCount; 
GLabel valTime; 
GLabel valData; 
GButton btnStart; 
GButton btnStop; 
3 Likes

Thanks a lot! This worked perfectly!!