G4P Lib - Slow Loading & GUI Builder Crashing Issues

Hi, two general issues, on a terrific library.

1). I noticed if I have some G4P controls, like toggle buttons or sliders, or whatever, and also the sketch has some static elements I’m drawing in draw(), like rectangles etc, the static elements load instantly and the G4P controls load about half a second later when I launch the sketch.

I’d like to either eliminate the G4P control draw latency, or alternately, delay drawing the static elements until the G4P controls render.

Otherwise, it’s a little jarring to have most of the interface load, and then controls appearing later. And this is for an app with customers, and it’d be great to have everything load at once, even if delayed.

2). Seems like no matter what I do, at random times, a sketch will suddenly crash when I’m using the GUI Builder. Then, no matter what I do, the sketch is permanently ruined. So I’ve taken to saving often, and when this happens, going to the previous version. But it would be great to have a way to get back to a useable version when this happens. Or better yet, have it not happen at all. Makes me very nervous to use the tool at all, although I think it’s great.

TIA for any insights or ideas.

Mike

Here’s the main sketch code:

// Need G4P library
import g4p_controls.*;
import processing.serial.*;

int LightGray = 209;
int DarkGray = 45;

int AppWidth = 800;
int AppHeight = 600;



public void setup(){
  size(800, 600, JAVA2D);
  
  createGUI();
  customGUI();
  
}

public void draw(){
  background(100);//230
  
 //Large BG rect
  noStroke();
  fill(DarkGray);
  rect(35, 60, 730, 490, 10);
    
}

// Use this method to add additional statements
// to customise the GUI controls
public void customGUI(){

}



Here’s the G4P gui code:

/* =========================================================
 * ====                   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 ddlPortsClick(GDropList source, GEvent event) { //_CODE_:ddlPorts:819097:
  println("ddlPorts - GDropList >> GEvent." + event + " @ " + millis());
  
} //_CODE_:ddlPorts:819097:

public void imgTogConnectClick(GImageToggleButton source, GEvent event) { //_CODE_:imgTogConnect:873837:
  println("imgTogButton1 - GImageToggleButton >> GEvent." + event + " @ " + millis());
  
} //_CODE_:imgTogConnect:873837:

public void imgBtnLogoClick(GImageButton source, GEvent event) { //_CODE_:imgBtnLogo:943362:
  println("imgBtnLogo - GImageButton >> GEvent." + event + " @ " + millis());
} //_CODE_:imgBtnLogo:943362:

public void imgBtnRefreshPortsClick(GImageButton source, GEvent event) { //_CODE_:imgBtnRefreshPorts:847314:
  println("imgBtnRefresh - GImageButton >> GEvent." + event + " @ " + millis());
 
} //_CODE_:imgBtnRefreshPorts:847314:

public void sldScenePicker_Change1(GCustomSlider source, GEvent event) { //_CODE_:sldScenePicker:226604:
  println("custom_slider1 - GCustomSlider >> GEvent." + event + " @ " + millis());
} //_CODE_:sldScenePicker:226604:

public void imgTogButton1_click1(GImageToggleButton source, GEvent event) { //_CODE_:imgTogButton1:324411:
  println("imgTogButton1 - GImageToggleButton >> GEvent." + event + " @ " + millis());
} //_CODE_:imgTogButton1:324411:



// 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("MusioTech Editor V1.0");
  ddlPorts = new GDropList(this, 542, 21, 164, 105, 4, 10);
  ddlPorts.setItems(loadStrings("list_819097"), 0);
  ddlPorts.setLocalColorScheme(GCScheme.SCHEME_15);
  ddlPorts.addEventHandler(this, "ddlPortsClick");
  lblPortStatus = new GLabel(this, 542, 43, 167, 16);
  lblPortStatus.setTextAlign(GAlign.RIGHT, GAlign.MIDDLE);
  lblPortStatus.setText(" ");
  lblPortStatus.setOpaque(false);
  imgTogConnect = new GImageToggleButton(this, 711, 18, "plugToggle4.png", "plugToggle4-over.png", 2, 1);
  imgTogConnect.addEventHandler(this, "imgTogConnectClick");
  imgBtnLogo = new GImageButton(this, 636, 561, 130, 30, new String[] { "Main-Red-Blue-white.png", "Main-Red-Blue-white.png", "Main-Red-Blue-white.png" } );
  imgBtnLogo.addEventHandler(this, "imgBtnLogoClick");
  imgBtnRefreshPorts = new GImageButton(this, 737, 19, 25, 24, new String[] { "Refresh-Up2.png", "Refresh-Over2.png", "Refresh-Up2.png" } );
  imgBtnRefreshPorts.addEventHandler(this, "imgBtnRefreshPortsClick");
  sldScenePicker = new GCustomSlider(this, 717, 157, 292, 36, "grey_blue");
  sldScenePicker.setTextOrientation(G4P.ORIENT_LEFT);
  sldScenePicker.setRotation(PI/2, GControlMode.CORNER);
  sldScenePicker.setLimits(1, 1, 8);
  sldScenePicker.setNbrTicks(8);
  sldScenePicker.setNumberFormat(G4P.INTEGER, 0);
  sldScenePicker.setOpaque(false);
  sldScenePicker.addEventHandler(this, "sldScenePicker_Change1");
  imgTogButton1 = new GImageToggleButton(this, 56, 453, "Rainbow-Icon-toggle9.png", 2, 1);
  imgTogButton1.addEventHandler(this, "imgTogButton1_click1");
}

// Variable declarations 
// autogenerated do not edit
GDropList ddlPorts; 
GLabel lblPortStatus; 
GImageToggleButton imgTogConnect; 
GImageButton imgBtnLogo; 
GImageButton imgBtnRefreshPorts; 
GCustomSlider sldScenePicker; 
GImageToggleButton imgTogButton1; 

All visual G4P controls have their own off-screen buffer to store their visual interface. This buffer is lazily updated so that drawing the control in the display is a two step process

  1. Update the buffer image if and only if the control’s state has changed since the last frame
  2. Copy the buffer image to the correct position position in the display

This is very efficient compared to redrawing the control from scratch every frame even if there is no change

When a sketch is launched all the control buffers are invalid so have to be created hence the small delay. So sorry there is no realistic alternative to this delay. :frowning_face:

========================================================================

It would be useful to know what versions of Processing, G4P and GUI Builder you are using.

I am not aware of any stability issues with the current version of GUI Builder. It would be foolish to claim that GUI Builder has no bugs but a program crashes when it hits a situation it can’t deal with. Try and think what you were doing when it crashed e.g. editing a control, scrolling the GUI Builder window …

One thing I recommend when using GUI Builder do not have multiple sketches open at tha same time, just GUI Builder and its associated sketch.

2 Likes

Thank you kindly Peter. It’s incredible to have a creator like you so active, and attentive.

So back to question 1 - is there any way to delay the display of the normal static elements until the G4P controls are ready to display?

And to 2, of course as a semi developer myself my comment was not all that useful; apologies. I’ll keep a sharp eye out for when/if it happens again, but I’m so paranoid that I’m saving multiple copies of each sketch constantly because I lost time having to remake a sketch when it did happen.

Anyway, amazing tool; hats off to you!

On a totally unrelated topic, any thoughts to create a right-click menu, or tooltip feature, for the lib? That would add a lot…

All my best, and thank you again!

Mike

G4P hooks into the Processing event cycle and draws the GUI after the draw() method has been executed so that the controls appear on top of the display so there is nothing in G4P to help.

I have not tried this so I have no idea if it works but might fit your needs …

void draw(){
    background(128); // choode your own colour
    if(frameCount <  2) return; // first two frames are blank but does not stop G4P
    // You normal drawing code
}

I deliberately avoided including menus and popup menus in G4P but tooltips is a good idea. :+1:

Ooops nearly forgot :partying_face: G4P V4.3.9 released 3th June 2023 includes tooltips (see example that comes with library)

2 Likes

Dude do you ever sleep??

Your solution does work! There is still a sliiiight delay after launching the sketch, but indeed everything loads simultaneously now! Just what I wanted! Totally acceptable for an app. I really appreciate it!

Also, I will check out the tooltips - wonderful!

Hey thank you so much Peter! Amazing support and caring for others!

I hope you are paid well in your day job. You deserve it.

Mike

BTW, tried the tooltip on a slider I had set to show vertically…the tooltip is vertical (sideways)! Any way to get it back to horizontal?

Feature is great Peter!

Mike

This might help :grin:

slider

import g4p_controls.*;


GCustomSlider slider; 

public void setup(){
  size(480, 320, JAVA2D);
  createGUI();
  customGUI();
}

public void draw(){
  background(230);
}

public void customGUI(){
  // You will have to experiment with the 2nd and 3th parameters to get 
  // the relative position for the tooltip.
  // Since the slider has been rotated 90 degrees the 2nd parameter affects
  // the vertical position and the 3rd parameter the horizontal position
  slider.setTip("Pick a number", -40, -50);
  slider.setTipHorz(true);
}

// Create all the slider control
public void createGUI(){
  G4P.messagesEnabled(false);
  surface.setTitle("Sketch Window");
  slider = new GCustomSlider(this, 200, 40, 230, 50, "grey_blue");
  slider.setRotation(PI/2, GControlMode.CORNER);
  slider.setLimits(0.5, 0.0, 1.0);
  slider.setNbrTicks(10);
  slider.setNumberFormat(G4P.DECIMAL, 2);
  slider.setOpaque(false);
}
2 Likes

@quark ,

Thou art a gentleman and a scholar. Thank you so much kind sir.

The level of support you provide on a free library is insane :smiling_face_with_three_hearts:

THANK YOU! :clap: