G4P java Concurrent Modification Exception Error when exit() called

Hi all,

Just getting a strange java.util.ConcurrentModificationException message when using multiple windows in G4P.

It all seems to work fine until I try to use an “Exit” button (calling exit()), and then I get the following:

java.util.ConcurrentModificationException
at java.base/java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:970)
at java.base/java.util.LinkedList$ListItr.next(LinkedList.java:892)
at g4p_controls.GWindowImpl.dispose(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1309)
at processing.core.PApplet.handleMethods(PApplet.java:1456)
at processing.core.PApplet.dispose(PApplet.java:3420)
at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:405)
ConcurrentModificationException

I’ve been googling this and it seems to be related to trying to remove items in an Arraylist while still iterating over the list, but I’m not doing that explicitly (although I’m not sure what’s happening behind the scenes in java or the library). I’m just trying to quit the whole app with exit().

Is there any guidance on how to avoid this error?

Thanks,

Mike

I suggest that you use the close() or forceClose() method for all secondary windows before exiting the app.

To make this automatic then you might try adding this method to your application (no promises that it will work out of the box) :grin:

// This assumes you have 2 windows win1 and win2
public void exit(){
  win1.close(); // or forceClose()
  win2.close(); // or forceClose()
  super.exit();
}
2 Likes

Wonderful Peter. I will give it a shot x.

:pray::two_hearts:

That did it!

I had to first check if the windows were null, and then also I had to use the forceClose() instead of close - but it worked!

Many thanks Peter!!!

Mike

By the way, I’m now getting an error about a missing GWindowAWT method, but I am not actively using it:

The GWindowAWT class cannot find this method 
	public void null(PApplet applet, GWinData windata) { /* code */ }

Any idea why? I tried just copy/pasting the code but it won’t accept it.

Thx for any thoughts. Seems to be a long process to get this right.

Mike

I have no idea because in the 15 years that G4P has been available this error message has never been reported before and there is insufficient information for me to even start looking for a solution.

For instance

  • did the error occur when a window was being created?
  • did the error occur when a window was being closed?
  • what code were you copying and pasting?
  • are you using GUI Builder?
  • do you know the source code being executed just prior to the error message?

If I am to emulate Sherlock Holmes and find a solution I need information, I need detail :grin:

2 Likes

Of course that’s not enough info. Sorry.

Can I ask where GWindowAWT class is located? I have not explicitly called it from the code anywhere. So there’s no place for me to put the suggested fix line.

Here is the code for all the additional optional window. Yes it’s a hot mess compared to the elegance with which you would do it I’m sure. If it gives no ideas to you, that’s fine too. I don’t expect you to write my code. But if you see anything with a glance, that would be helpful.


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                 GLOBAL COLOR THEME BOX                                                         //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


public void globalCTDraw(PApplet app, GWinData data){
  app.background(127);
  globalCT.image(editIcon, 150, 10);    
}
  
void showGlobalCT() {
  int windowWidth = 350;
  int windowHeight = 245;
  if (globalCT == null) {
    globalCT = GWindow.getWindow(this, "MusioTech", width/2 + 120, height/2 + 65, windowWidth, windowHeight, JAVA2D);
    globalCT.setActionOnClose(G4P.HIDE_WINDOW);
    globalCT.addMouseHandler(this, "globalCTMouse");
    globalCT.addKeyHandler(this, "globalCTKey");
    globalCT.addDrawHandler(this, "globalCTDraw");    
    
    lblMessage = new GLabel(globalCT, 40, 65, 260, 50);
    lblMessage.setText("Global Color Theme:");
    lblMessage.setLocalColorScheme(GCScheme.SCHEME_15);
    lblMessage.setOpaque(false);
    lblMessage.setTextAlign(GAlign.CENTER, GAlign.MIDDLE);
    lblMessage.setFont(new Font("Noto Sans Bold", G4P.PLAIN, 24));
    
    ddlEditGlobalCT = new GDropList(globalCT, 50, 110, 250, 132, 3, 10);
    //ddlEditGlobalCT.setItems(loadStrings("list_819097"), 0);
    ddlEditGlobalCT.setLocalColorScheme(GCScheme.SCHEME_9);
    ddlEditGlobalCT.addEventHandler(this, "ddlEditGlobalCT_click");
    ddlEditGlobalCT.setFont(new Font("Noto Sans Bold", G4P.PLAIN, 24));
    for (byte i = 0; i < (presetColorSetCount + customColorSetCount); i++) {
      ddlEditGlobalCT.addItem(colorSetNames[i]); 
    } 
    
    btnOKglobalCT = new GButton (globalCT, 90, 175, 80, 30, "OK");
    btnOKglobalCT.addEventHandler(this, "btnOKglobalCT_clicked");
    btnOKglobalCT.setLocalColorScheme(GCScheme.SCHEME_9);
    
    btnCancelglobalCT = new GButton (globalCT, 190, 175, 80, 30, "Cancel");
    btnCancelglobalCT.addEventHandler(this, "btnCancelglobalCT_clicked");
    btnCancelglobalCT.setLocalColorScheme(GCScheme.SCHEME_9);
    
  }//if (messageBox != null) {
  else {
    globalCT.setVisible(true); 
  } 

}//end void showGlobalCT

public void globalCTMouse(PApplet app, GWinData data, MouseEvent event) {
  //float e = event.getCount();
  //colorThemeSelected += e;
  
  //if (ddlEditGlobalCT.hasFocus()) {
  //  if (colorThemeSelected > presetColorSetCount + customColorSetCount) colorThemeSelected = presetColorSetCount + customColorSetCount - 1;
  //  if (colorThemeSelected < 0) colorThemeSelected = 0;
  //  ddlEditGlobalCT.setSelected(colorThemeSelected);
  //}
}

public void globalCTKey(PApplet app, GWinData data, KeyEvent event) {
  if (event.getKey() == RETURN || event.getKey() == ENTER) globalCT.setVisible(false);
}

//public class MyMsgData extends GWinData {
//    // The variables can be anything you like.
//    public int lastClickX,lastClickY;
//}

public void btnOKglobalCT_clicked(GButton source, GEvent event) {
  rainbow.getRainbowColors();//rainbow.setRainbowColors(ddlEditGlobalCT.getSelectedIndex());
  rainbow.display();
  lblGlobalColorTheme.setText("Global: " + colorSetNames[globalColorSetRow]);
  globalCT.setVisible(false);  
}

public void btnCancelglobalCT_clicked(GButton source, GEvent event) {
  globalCT.setVisible(false);  
}

public void ddlEditGlobalCT_click(GDropList source, GEvent event) { //_CODE_:dropList1:306266:
  println("ddlEditGlobalCT - GDropList >> GEvent." + event + " @ " + millis());
  globalColorSetRow = source.getSelectedIndex();
} //_CODE_:dropList1:306266:

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                            LOADING BOX                                                         //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public void loadingBoxDraw(PApplet app, GWinData data){
  app.background(127);    
}
  
void showLoadingBox(String strTitle, String strMessage) {
  if (loadingBox == null) {
    loadingBox =  GWindow.getWindow(this, strTitle, width/2 + 120, height/2 + 65, 240, 130, JAVA2D);
    loadingBox.setActionOnClose(G4P.HIDE_WINDOW);
    loadingBox.addDrawHandler(this, "loadingBoxDraw");
    //loadingBox.addMouseHandler(this, "loadingBoxMouse");
    loadingBox.addKeyHandler(this, "loadingBoxKey");
    
    GAnimIcon loadingIcon = new GAnimIcon(loadingBox, Loading, 8, 1, 150); 
    loadingLabel = new GLabel(loadingBox, 10, 20, 80, 80, "");
    loadingLabel.setLocalColorScheme(GCScheme.SCHEME_15);//SCHEME_15
    loadingLabel.setTextAlign(GAlign.CENTER, null);
    loadingLabel.setIcon(loadingIcon, GAlign.NORTH, null, null);
    loadingLabel.getIcon().animate();  
    
    lblMessage = new GLabel(loadingBox, 80, 45, 120, 30);
    lblMessage.setText(strMessage);
    lblMessage.setLocalColorScheme(GCScheme.SCHEME_15);
    lblMessage.setOpaque(false);
    lblMessage.setTextAlign(GAlign.LEFT, GAlign.MIDDLE);
    lblMessage.setFont(new Font("Noto Sans Bold", G4P.PLAIN, 24));
  }// if (loadingBox == null) }
  else {    
    lblMessage.setText(strMessage);
    loadingBox.setVisible(true);
  }
}//end void showLoadingBox
  
//public void preferencesMouse(PApplet app, GWinData data, MouseEvent event) {
//    // Saves doing it for every variable in MyData class
//    MyData myData = (MyData) data;
//    if(event.getAction() == MouseEvent.CLICK){
//      myData.lastClickX = mouseX;
//      myData.lastClickY = mouseY;
//    }
//}

public void loadingBoxKey(PApplet app, GWinData data, KeyEvent event) {


}

//public class MyData extends GWinData {
//    // The variables can be anything you like.
//    public int lastClickX,lastClickY;
//}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                           MESSAGE BOX                                                          //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public void msgBoxYesDraw(PApplet app, GWinData data){
  app.background(127);
  msgBox.image(yesIcon, 122, 5);    
}

public void msgBoxNoDraw(PApplet app, GWinData data){
  app.background(127);
  msgBox.image(noIcon, 122, 5);    
}

public void msgBoxInfoDraw(PApplet app, GWinData data){
  app.background(127);
  msgBox.image(infoIcon, 122, 5);    
}

public void msgBoxWarningDraw(PApplet app, GWinData data){
  app.background(127);
  msgBox.image(warningIcon, 122, 5);    
}
public void msgBoxCriticalDraw(PApplet app, GWinData data){
  app.background(127);
  msgBox.image(criticalIcon, 122, 5);    
}

public void msgBoxBackupOKDraw(PApplet app, GWinData data){
  app.background(127);  
  msgBox.image(backupOKIcon, 122, 5);  
}
  
void showMsgBox(int boxStyle, String strTitle, String strMessage) {
  if (msgBox == null) {
    msgBox =  GWindow.getWindow(this, strTitle, width/2 + 120, height/2 + 65, 300, 160, JAVA2D);
    msgBox.setActionOnClose(G4P.HIDE_WINDOW);
    msgBox.addMouseHandler(this, "msgBoxMouse");
    msgBox.addKeyHandler(this, "msgBoxKey");
    
    lblMessage = new GLabel(msgBox, 25, 55, 250, 50);
    lblMessage.setText(strMessage);
    lblMessage.setLocalColorScheme(GCScheme.SCHEME_15);
    lblMessage.setOpaque(false);
    lblMessage.setTextAlign(GAlign.CENTER, GAlign.MIDDLE);
    lblMessage.setFont(new Font("Noto Sans Bold", G4P.PLAIN, 14));
    
    btnOKmsgBox = new GButton (msgBox, 112, 115, 80, 30, "OK");
    btnOKmsgBox.addEventHandler(this, "btnOKmsgBox_clicked");
    btnOKmsgBox.setLocalColorScheme(GCScheme.SCHEME_9);
    
    if (boxStyle == YES) {
      msgBox.addDrawHandler(this, "msgBoxYesDraw");    
    }
    else if (boxStyle == NO) {
      msgBox.addDrawHandler(this, "msgBoxNoDraw");    
    }
    else if (boxStyle == INFO) {
      msgBox.addDrawHandler(this, "msgBoxInfoDraw");     
    }
    else if (boxStyle == WARNING) {
      msgBox.addDrawHandler(this, "msgBoxWarningDraw");  
    } 
    else if (boxStyle == CRITICAL) {
      msgBox.addDrawHandler(this, "msgBoxCriticalDraw");  
    } 
    
    else if (boxStyle == BACKUPOK) {
      msgBox.addDrawHandler(this, "msgBoxBackupOKDraw");    
    }
  }//if (messageBox != null) {
  else {
    lblMessage.setText(strMessage);
    msgBox.setTitle(strTitle);
    msgBox.setVisible(true);  
  }
  msgBox.addDrawHandler(this, null);    
  if (boxStyle == YES) {
    msgBox.addDrawHandler(this, "msgBoxYesDraw");    
  }
  else if (boxStyle == NO) {
    msgBox.addDrawHandler(this, "msgBoxNoDraw");    
  }
  else if (boxStyle == INFO) {
    msgBox.addDrawHandler(this, "msgBoxInfoDraw");     
  }
  else if (boxStyle == WARNING) {
    msgBox.addDrawHandler(this, "msgBoxWarningDraw");  
  } 
  else if (boxStyle == CRITICAL) {
    msgBox.addDrawHandler(this, "msgBoxCriticalDraw");  
  } 
  else if (boxStyle == BACKUPOK) {
    msgBox.addDrawHandler(this, "msgBoxBackupOKDraw");    
  }
}

public void msgBoxMouse(PApplet app, GWinData data, MouseEvent event) {
    // Saves doing it for every variable in MyData class
    //MyMsgData myData = (MyMsgData) data;
    //if(event.getAction() == MouseEvent.CLICK){
    //  MyMsgData.lastClickX = mouseX;
    //  MyMsgData.lastClickY = mouseY;
    //}
}

public void msgBoxKey(PApplet app, GWinData data, KeyEvent event) {
  if (event.getKey() == RETURN || event.getKey() == ENTER) msgBox.setVisible(false);
}

//public class MyMsgData extends GWinData {
//    // The variables can be anything you like.
//    public int lastClickX,lastClickY;
//}

public void btnOKmsgBox_clicked(GButton source, GEvent event) {  
  msgBox.setVisible(false);  
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                QUESTION BOX                                                    //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public void qBoxDraw(PApplet app, GWinData data){
  app.background(127);
  app.image(questionIcon, 122, 5);    
}
  
void showQBox(String strTitle, String strMessage, int action) {
  int windowWidth = 300;
  int windowHeight = 160;
  if (qBox == null) {
    qBox =  GWindow.getWindow(this, strTitle, width/2 + 120, height/2 + 65, 300, 160, JAVA2D);
    qBox.setActionOnClose(G4P.HIDE_WINDOW);
    qBox.addMouseHandler(this, "qBoxMouse");
    qBox.addKeyHandler(this, "qBoxKey");
    qBox.addDrawHandler(this, "qBoxDraw");  
    
    lblMessage = new GLabel(qBox, 25, 55, 250, 50);
    lblMessage.setText(strMessage);
    lblMessage.setLocalColorScheme(GCScheme.SCHEME_15);
    lblMessage.setOpaque(false);
    lblMessage.setTextAlign(GAlign.CENTER, GAlign.MIDDLE);
    lblMessage.setFont(new Font("Noto Sans Bold", G4P.PLAIN, 14));
    
    btnYesQBox = new GButton (qBox, windowWidth/2 + 20, windowHeight - buttonYOffset, 80, 30, "Yes");
    btnYesQBox.setLocalColorScheme(GCScheme.SCHEME_9);
    switch (action) {
      case 0://backup
        btnYesQBox.addEventHandler(this, "qBoxBackupDevice_click");
        break;
      case 1://restore
        btnYesQBox.addEventHandler(this, "qBoxRestoreDevice_click");
        break;      
    }
    
    btnNoQBox = new GButton (qBox,  windowWidth/2 - buttonWidth - 20, windowHeight - buttonYOffset, 80, 30, "No");
    btnNoQBox.addEventHandler(this, "btnNoQBox_click");
    btnNoQBox.setLocalColorScheme(GCScheme.SCHEME_9);
  }//if (qBox != null) {
  else {
     btnYesQBox.addEventHandler(this, null);
    switch (action) {
      case 0://backup
        btnYesQBox.addEventHandler(this, "qBoxBackupDevice_click");
        break;
      case 1://restore
        btnYesQBox.addEventHandler(this, "qBoxRestoreDevice_click");
        break;      
    }
    lblMessage.setText(strMessage);
    qBox.setTitle(strTitle);
    qBox.setVisible(true);  
  }    
}

public void qBoxMouse(PApplet app, GWinData data, MouseEvent event) {
    // Saves doing it for every variable in MyData class
    //MyMsgData myData = (MyMsgData) data;
    //if(event.getAction() == MouseEvent.CLICK){
    //  MyMsgData.lastClickX = mouseX;
    //  MyMsgData.lastClickY = mouseY;
    //}
}

public void qBoxKey(PApplet app, GWinData data, KeyEvent event) {
  //if (event.getKey() == RETURN || event.getKey() == ENTER) msgBox.setVisible(false);
}

//public class MyMsgData extends GWinData {
//    // The variables can be anything you like.
//    public int lastClickX,lastClickY;
//}

public void btnNoQBox_click(GButton source, GEvent event) {  
  qBox.setVisible(false);    
}

public void qBoxBackupDevice_click(GButton source, GEvent event) {
  qBox.setVisible(false);  
    
}
public void qBoxRestoreDevice_click(GButton source, GEvent event) {
  qBox.setVisible(false);  
    
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                             OPTIONS BOX                                                        //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


public void optionsDraw(PApplet app, GWinData data){
    app.background(127);
    app.image(optionsIcon, 123, 10);   
    //app.stroke(100);
    //app.strokeWeight(2);
    //app.fill(127);
    //app.rect(15, 70, 270, 70, 5);
  }
  
void createOptionsWindow() {
  int windowWidth = 300;
  int windowHeight = 200;
  options =  GWindow.getWindow(this, "Options", width/2 + 120, height/2 + 70, windowWidth, windowHeight, JAVA2D);
  options.setActionOnClose(G4P.HIDE_WINDOW);
  options.addDrawHandler(this, "optionsDraw");
  options.addMouseHandler(this, "optionsMouse");
  options.addKeyHandler(this, "optionsKey");
  //options.addData(new MyData());
  cbShowToolTips = new GCheckbox(options, 22, 80, 120, 20, "Show Tooltips");
  cbShowToolTips.setLocalColorScheme(GCScheme.SCHEME_15);
  cbShowToolTips.setSelected(blnShowToolTip);
  cbShowToolTips.addEventHandler(this, "cbShowToolTips_clicked");
  
  btnCancelOptions = new GButton (options, windowWidth/2 - buttonWidth - 15, windowHeight - buttonYOffset, buttonWidth, buttonHeight, "Cancel");
  btnCancelOptions.addEventHandler(this, "btnCancelOptions_clicked");
  btnCancelOptions.setLocalColorScheme(GCScheme.SCHEME_9);
  
  btnOKOptions = new GButton (options, windowWidth/2 + 15, windowHeight - buttonYOffset, buttonWidth, buttonHeight, "OK");
  btnOKOptions.addEventHandler(this, "btnOKOptions_clicked");
  btnOKOptions.setLocalColorScheme(GCScheme.SCHEME_9);
}
  
public void optionsMouse(PApplet app, GWinData data, MouseEvent event) {
    // Saves doing it for every variable in MyData class
    //MyData myData = (MyData) data;
    //if(event.getAction() == MouseEvent.CLICK){
    //  myData.lastClickX = mouseX;
    //  myData.lastClickY = mouseY;
    //}
}

public void optionsKey(PApplet app, GWinData data, KeyEvent event) {
  if (event.getKey() == RETURN || event.getKey() == ENTER) options.setVisible(false);
}

public class MyData extends GWinData {
    // The variables can be anything you like.
    public int lastClickX,lastClickY;
}

public void cbShowToolTips_clicked(GCheckbox source, GEvent event) {
  if (cbShowToolTips.isSelected()) blnShowToolTip = true;
  else blnShowToolTip = false;
  showHideToolTips();  
}

void showHideToolTips() { 
    
  if (blnShowToolTip) toolTipGap = 0;
  else toolTipGap = 1000; 
  setTooltips();  
}

public void btnCancelOptions_clicked(GButton source, GEvent event) {
  println("CANCEL CLICKED!");
  if (options != null) options.setVisible(false);  
}

public void btnOKOptions_clicked(GButton source, GEvent event) {
  println("OK CLICKED!");
  try{
    optString[1] = str(blnShowToolTip);
    saveStrings(dataPath("") +"/options.txt", optString);
  }
  catch(Exception e) {
    e.printStackTrace();
  }
  if (options != null) options.setVisible(false);  
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                             BACKUP & RESTORE                                                        //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

public void backupAndRestoreDraw(PApplet app, GWinData data){
    app.background(127);
    app.image(backupIcon, 123, 10);   
    //app.stroke(100);
    //app.strokeWeight(2);
    //app.fill(127);
    //app.rect(15, 70, 270, 70, 5);
  }
  
void showbackupAndRestoreWindow() {
  int windowWidth = 300;
  int windowHeight = 200;
  if (backupAndRestore == null) {
    backupAndRestore =  GWindow.getWindow(this, "Backup & Restore", width/2 + 120, height/2 + 70, windowWidth, windowHeight, JAVA2D);
    backupAndRestore.setActionOnClose(G4P.HIDE_WINDOW);
    backupAndRestore.addDrawHandler(this, "backupAndRestoreDraw");
    backupAndRestore.addMouseHandler(this, "backupAndRestoreMouse");
    backupAndRestore.addKeyHandler(this, "backupAndRestoreKey");  
    
    imgBtnBackupBackup = new GImageButton(backupAndRestore, windowWidth/2 - buttonWidth - 5, windowHeight - 130, 53, 53, new String[] { "backupButtonLarger3Up.png", "backupButtonLarger3Over.png", "backupButtonLarger3Pressed.png" } );
    imgBtnBackupBackup.addEventHandler(this, "imgBtnBackupBackup_click");
    imgBtnBackupBackup.setTip("Backup", GAlign.CENTER, GAlign.NORTH, toolTipGap);
    
    imgBtnRestoreBackup = new GImageButton(backupAndRestore, windowWidth/2 + 31, windowHeight - 130, 53, 53, new String[] { "restoreButtonLarger3Up.png", "restoreButtonLarger3Over.png", "restoreButtonLarger3Pressed.png" } );
    imgBtnRestoreBackup.addEventHandler(this, "imgBtnRestoreBackup_click");
    imgBtnRestoreBackup.setTip("Restore", GAlign.CENTER, GAlign.NORTH, toolTipGap);
    
    btnOKBackup = new GButton (backupAndRestore, windowWidth/2 - buttonWidth/2, windowHeight - buttonYOffset, buttonWidth, buttonHeight, "OK");
    btnOKBackup.addEventHandler(this, "btnOKBackup_clicked");
    btnOKBackup.setLocalColorScheme(GCScheme.SCHEME_9);
  }
  else {
    imgBtnBackupBackup.setTip("Backup", GAlign.CENTER, GAlign.NORTH, toolTipGap);
    imgBtnRestoreBackup.setTip("Restore", GAlign.CENTER, GAlign.NORTH, toolTipGap);
    backupAndRestore.setVisible(true);
  }
}
  
public void backupAndRestoreMouse(PApplet app, GWinData data, MouseEvent event) {
    // Saves doing it for every variable in MyData class
    //MyData myData = (MyData) data;
    //if(event.getAction() == MouseEvent.CLICK){
    //  myData.lastClickX = mouseX;
    //  myData.lastClickY = mouseY;
    //}
}

public void backupAndRestoreKey(PApplet app, GWinData data, KeyEvent event) {
  if (event.getKey() == RETURN || event.getKey() == ENTER) options.setVisible(false);
}

//public class MyData extends GWinData {
//    // The variables can be anything you like.
//    public int lastClickX,lastClickY;
//}

public void imgBtnBackupBackup_click(GImageButton imagebutton, GEvent event) {
  println("BACKUP CLICKED!"); 
  showQBox("Backup", "Backup all device data?", performBackup);
  if (backupAndRestore != null) backupAndRestore.setVisible(false);  
}

public void imgBtnRestoreBackup_click(GImageButton imagebutton, GEvent event) {
  println("RESTORE CLICKED!");  
  showQBox("Restore", "Restore all device data?", performRestore);
  if (backupAndRestore != null) backupAndRestore.setVisible(false);
}


//public void btnCancelBackup_clicked(GButton source, GEvent event) {
//  println("CANCEL CLICKED!");
//  if (backupAndRestore != null) backupAndRestore.setVisible(false);  
//}

public void btnOKBackup_clicked(GButton source, GEvent event) {
  println("OK CLICKED!");

  if (backupAndRestore != null) backupAndRestore.setVisible(false);  
}
//public void null(PApplet applet, GWinData windata) { /* code */ }

Also here’s the declaration of the windows, prior to setup as globals:

///// Custom Controls /////

GWindow options = null;
GWindow loadingBox = null;
GWindow msgBox = null;
GWindow globalCT = null;
GWindow backupAndRestore = null;
GWindow backup = null;
GWindow restore = null;
GWindow qBox = null;

GCheckbox cbShowToolTips;
GButton btnOKOptions;
GButton btnCancelOptions;
GButton btnOKmsgBox;
GButton btnOKglobalCT;
GButton btnCancelglobalCT;
GLabel loadingLabel;
GButton loadingButton;
GLabel lblMessage;
GDropList ddlEditGlobalCT;
GButton btnCancelBackup;
GButton btnOKBackup;
GButton btnBackup;
GButton btnRestore;
GImageButton imgBtnBackupBackup;
GImageButton imgBtnRestoreBackup;
GButton btnYesQBox;
GButton btnNoQBox;

PImage Loading;
PImage warningIcon;
PImage criticalIcon;
PImage infoIcon;
PImage editIcon;
PImage optionsIcon;
PImage backupIcon;
PImage yesIcon;
PImage noIcon;
PImage questionIcon;
PImage backupOKIcon;

int PLAIN = 0;
int INFO = 1;
int WARNING = 2;
int CRITICAL = 3;
int YES = 4;
int NO = 5;
int BACKUPOK = 6;

int buttonWidth = 80;
int buttonHeight = 30;
int buttonXOffset = 100;
int buttonYOffset = 50;

int performBackup = 0;
int performRestore = 1;

//////////////////////////

Also I did not answer your questions; sorry.

  • did the error occur when a window was being created?
    LIKELY. There are some error window boxes if data doesn’t load, but since there is no indication of WHY this is happening, or WHEN or HOW, and since I’m not referencing that code at all, it’s a mystery.
  • did the error occur when a window was being closed?
    No, for sure, I hadn’t closed any windows
  • what code were you copying and pasting?
public void null(PApplet applet, GWinData windata) { /* code */ }
  • are you using GUI Builder?
    No.
  • do you know the source code being executed just prior to the error message?
    It seems to be happening when the CRITICAL version of the showMsgBox void is called, but it’s hard to tell for sure. However definitely it’s connected with showing a messagebox. And that message is new.

Feel free to disregard this issue. I totally understand how obtuse and ridiculous it is for me to ask without a clear request and clear code for you to follow.

No worries mate; I appreciate you and your library and I don’t want to burn you out.

mike

EDIT: Found the issue. I was using different draw handlers depending on which icon/message to use, and I had read in java to remove an event handler to set it to null.

But clearly it’s different in processing.

anyway, this was the problem line I think:

msgBox.addDrawHandler(this, null);

I’m not sure how to handle using a different event handler after it’s been assigned, but I’ll see what happens.

Thanks again for your kindness Peter. I never should have posted before spending a bit more time working the issue; it’s been a bit stressful lately so thanks for your grace.

Well done that is the offending line.

In this line you are naming the function that will be the draw method for this window.

IMPORTANT NOTES:

  1. the draw method is not the same as an event handler
  2. every window must have its own draw method
  3. windows cannot share a draw method

To create a new window in G4P we use the GWindow.getWindow(...) method. The type of window depends on the last parameter passed - JAVA2D, P2D or P3D

JAVA2D

  • uses Java AWT (Abstract Window Toolkit)
  • a Java Swing frame (JFrame) is used for the window
  • G4P class GWindowAWT

P2D, P3D

  • based on OpenGL it uses NEWT (Native Event Window Toolkit)
  • an OpenGL window is created
  • G4P class GWindowNEWT

The classes GWindowAWT and GWindowNEWT both inherit from GWindow which allows a common API for all G4P windows through polymorphism.

3 Likes

Fantastic info Peter! Thank you!

To add to your IMPORTANT NOTES -

Can I change a window’s draw handler when I show/hide it? Or that not allowed?

Thank you again, I really appreciate your expertise, and most of all, your precious time.

Mike

Why would you want to do that?

1 Like

Because I’m trying to show different icons for one dialog box depending on state.

Additionally, I’d like to be able to change the event handler on show/hide of visibility.

I’m probably going about all this totally wrong aren’t I…

I believe so… :smile:

If by dialog box you mean the dialog boxes created with the G4P.showMessage method or one of the G4P.select???methods then they use either Swing or OS dialog boxes and this has been covered in this discussion so I have nothing to add.
If on the other hand you are talking about your own dialog boxes created with GWindow then which icons are you talking about?

Which event handler are you talking about? Why do you need a different event handler when the window is invisible? Doesn’t make sense to me.

I’m trying to have an “all purpose” message box that will show various icons whether the message is “info” or “warning” etc. Using the dialog boxes I created, not using Swing or anything else. Just your library only.

I’m not trying to change event handlers and draw handlers when the box is hidden - only when I show it again.

Because, for instance, I create the box with a given event and draw handler set. Then I hide it.

Next time I want to show it again, but this time use a different icon, and different button action.

I’m trying to make it so I don’t have to have 47 different windows to handle the various tasks of the app, and make messaging streamlined.

Anyway, I do appreciate your insights, and I thank you for your time. Truly :slight_smile: