How to include G4P controls with saveFrame

When I use the “saveFrame” function it does take a screenshot of the sketch but does not take all its elements.
For example, this first image is a screenshot taken with the Windows tool:

And this one is a screenshot taken with the “saveFrame” function:

For some reason it does not save the buttons in the screenshot.

Code:

import g4p_controls.*;
import processing.serial.*;
import peasy.*;
Serial puerto; // se declara una variable para la com. serial
float datoanterior = 0; //Dato anterior del sensor de pulso.
PImage img; //Llamar imagen. 
PImage img2; //Llamar imagen. 
PImage img3;
boolean newData = false;
int xPos = 0;         // posición horizontal del gráfico
// Variables para dibujar una línea continua de la gráfica. 
int lastxPos=1;
int lastheight=0;
//Fin de gráfica...............

//Datos entrantes............
String datas; //_________________________________________ latest arduino text line
float[] datai; //__________________________________________ as array of integers
boolean log = false; //__________________________________ diagnostic print
float temperatura,aire,humedad,mmHg;

void conectarUSB(){
  puerto = new Serial(this,Serial.list()[0], 9600); //Busca puerto serie conectado automáticamente.
  //puerto = new Serial(this, portName, 9600);
  puerto.clear();
  puerto.bufferUntil('\n');
}
  

void serialEvent(Serial puerto) { //__________________________ handle serial data
  datas = trim(puerto.readStringUntil('\n'));
  if (datas != null) {
    //println(datas); //________________________ optional print every GOOD line
    datai = float( split(datas, ",") ); //_________________ create int array from CSV type line
    datai[0] = float(datas);           // convertir a un número.
    datai[0] = map(datai[2], 0, 1023, 0, height); //mapa a la altura de la pantalla y datos de la gráfica.
    newData = true; 
    if ( datai.length >= 3 ) { //________________________ if find min 2 "," and understood 3 integer
       for ( int i=0; i < datai.length; i++ ) 
       if ( log ) print(datai[i]+" , ");
       if ( log ) println();
       temperatura = datai[1];
       aire = datai[2];
       humedad = datai[3];
       mmHg = datai[4];
       
    } else println("shortline ",datas);
  }
}

//..................Fin datos entrantes.    


public void setup(){
  size(1000, 600, JAVA2D); //Tamaño de la ventana principal
  createGUI();
  customGUI();
   background(17,34,51);      // Color de fondo principal 
   rect(0, 95, 999, 355,1); // Tamaño del rectángulo blanco donde se grafican los datos
   stroke(196,196,196); // Color de la línea del cuadriculado
   fill(258,258,258);//Color del Texto 
   textSize(13); 
 
   for (int i = 0; i < 999; i=i+20) { // Dibuja el enrejado vertical de la zona de graficación  
  line(20+i, 95,20+i, 450);
  }  
  for (int i = 0; i < 350; i=i+20) { // Dibuja el enrejado horizontal de la zona de graficación  
  line(0, 95+i, 1000, 95+i);
  }
  
}



public void draw(){
    println(datai);
    fill(17,34,51); // Color del rectángulo detrás de la hora. 
    rect(820, 0, 130, 80,1); //Rectángulo detrás de la hora.
    rect(5, 5, 90, 85,1); //Rectángulo detrás del USB.
    fill(258,258,258);//Color del Texto arriba derecha. 
    textSize(13); 
    text("Fecha: "+day()+"/"+month()+"/"+year(),828,30);
    text("Hora: "+hour()+":"+minute()+":"+second(),828,50);
    text("Conectar USB",5,85);
    fill(17,34,51);  
    rect(7, 451, 500, 145,1); //Rectángulo detrás de la temperatura. 
    fill(258,258,258);//Color del Texto de la temperatura. 
    textSize(16); 
    text(temperatura+"°C",20,590);
    text("Set",55,475);
    text("37"+"°C",55,495);
    text(humedad+"%",105,540);
    text("Humedad",91,590);
    text("Ciclos",310,590);
    text("8",330,528);
    text(mmHg,410,590);
    img = loadImage ("corazon.png");
    img2 = loadImage ("gota humedad.png");
    img2.resize(0,110);
    image(img2, 90, 460);
    
    img3 = loadImage ("mmhg2.png");
    img3.resize(0,100);
    image(img3, 395, 465);
    
   
    
    //Mostrar datos del sensor de pulso. 
    if(mmHg>0){  
    datoanterior = mmHg;
    //text("BPM: " + inByte[4],205,590);   
   img.resize(0,90);
   image(img, 200, 470);
    }
    
    else {
    //text("BPM: " + datoanterior,205,590);
    img.resize(0,100);
    image(img, 200, 470);
    }
    //Fin datos del sensor de pulso. 
    
 if (newData) {
    stroke(17,34,51);     //Color de la línea graficadora. 
    strokeWeight(1);        //Grosor de la línea graficadora.
    line(lastxPos, lastheight, xPos, height - datai[0]); 
    lastxPos= xPos;
    lastheight= int(height-datai[0]);
    
     // Dibujando una línea desde Last inByte hasta la nueva.
     // en el borde de la ventana, regrese al principio:
    if (xPos >= width) {
      xPos = 0;
      lastxPos= 0;
      saveFrame( "Pantallazos Automáticos cada 30s"+"/"+day()+"-"+month()+"-"+year()+" a las "+hour()+"_"+minute() +" con "+ second()+"s"+ ".png") ; //dar nombre de fecha a los pantallazos
     // background(17,34,51);  //Clear the screen.
      rect(0, 95, 999, 355,1); // Tamaño del rectángulo blanco donde se grafican los datos
      stroke(196,196,196); // Color de la línea del cuadriculado
   
      for (int i = 0; i < 999; i=i+20) { // Dibuja el enrejado vertical de la zona de graficación  
      line(20+i, 95,20+i, 450);
    }  
      for (int i = 0; i < 350; i=i+20) { // Dibuja el enrejado horizontal de la zona de graficación  
      line(0, 95+i, 1000, 95+i);
  }
    } 
    else {
      // Incrementa la posición horizontal.
      xPos++;
    }
   newData =false;
 }
}
  
public void customGUI(){

}



//Enviar datos al arduino............
void Encender(){ // Encender LED
  puerto.write('E');
}

void Apagar(){ //Apagar LED
  puerto.write('A');
  
}

void GuardarPNG(){
  saveFrame( "Pantallazos Guardados con Click"+"/"+day()+"-"+month()+"-"+year()+" a las "+hour()+"_"+minute() +" con "+ second()+"s"+ ".png") ; //dar nombre de fecha a los pantallazos
}


void Terminar(){ // Salir
  exit(); 
}

GUI code:

public void Salir_click1(GButton source, GEvent event) { //_CODE_:SalirBoton:948718:
  //println("button1 - GButton >> GEvent." + event + " @ " + millis());
  Terminar();
} //_CODE_:SalirBoton:948718:

public void ON_click1(GButton source, GEvent event) { //_CODE_:buttonON:569136:
   Encender();
  //println("button2 - GButton >> GEvent." + event + " @ " + millis());
} //_CODE_:buttonON:569136:

public void OFF_click1(GButton source, GEvent event) { //_CODE_:OFFboton:956947:
   Apagar();
  //println("buttonOFF - GButton >> GEvent." + event + " @ " + millis());
} //_CODE_:OFFboton:956947:

public void guardarPNG_click1(GButton source, GEvent event) { //_CODE_:GuardarPNG:848467:
GuardarPNG();
 // println("GuardarPNG - GButton >> GEvent." + event + " @ " + millis());
} //_CODE_:GuardarPNG:848467:

public void NombreSesione(GTextField source, GEvent event) { //_CODE_:NombreSesion:586660:
  //println("textfield1 - GTextField >> GEvent." + event + " @ " + millis());
} //_CODE_:NombreSesion:586660:

public void NotasAdicionales_change1(GTextArea source, GEvent event) { //_CODE_:NotasAdiocionales:485293:
  //println("textarea1 - GTextArea >> GEvent." + event + " @ " + millis());
} //_CODE_:NotasAdiocionales:485293:

public void imgRaton_click1(GImageButton source, GEvent event) { //_CODE_:ImagenRaton:688501:
 // println("imgButton1 - GImageButton >> GEvent." + event + " @ " + millis());
} //_CODE_:ImagenRaton:688501:

public void TempBoton_click1(GImageButton source, GEvent event) { //_CODE_:TempBoton:598457:
  println("TempBoton - GImageButton >> GEvent." + event + " @ " + millis());
} //_CODE_:TempBoton:598457:

public void Ciclo_click1(GImageButton source, GEvent event) { //_CODE_:Ciclo:743652:
  println("Ciclo - GImageButton >> GEvent." + event + " @ " + millis());
} //_CODE_:Ciclo:743652:

public void ConectarUSB_click1(GImageButton source, GEvent event) { //_CODE_:ConectarUSB:531772:
   conectarUSB();
  //println("ConectarUSB - GImageButton >> GEvent." + event + " @ " + millis());
} //_CODE_:ConectarUSB:531772:



// 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");
  SalirBoton = new GButton(this, 649, 515, 80, 30);
  SalirBoton.setText("Salir");
  SalirBoton.setLocalColorScheme(GCScheme.CYAN_SCHEME);
  SalirBoton.addEventHandler(this, "Salir_click1");
  buttonON = new GButton(this, 132, 25, 32, 30);
  buttonON.setText("ON");
  buttonON.setLocalColorScheme(GCScheme.CYAN_SCHEME);
  buttonON.addEventHandler(this, "ON_click1");
  OFFboton = new GButton(this, 177, 25, 32, 30);
  OFFboton.setText("OFF");
  OFFboton.setLocalColorScheme(GCScheme.CYAN_SCHEME);
  OFFboton.addEventHandler(this, "OFF_click1");
  togGroup1 = new GToggleGroup();
  togGroup2 = new GToggleGroup();
  GuardarPNG = new GButton(this, 229, 25, 92, 30);
  GuardarPNG.setText("Guardar PNG");
  GuardarPNG.setLocalColorScheme(GCScheme.CYAN_SCHEME);
  GuardarPNG.addEventHandler(this, "guardarPNG_click1");
  NombreSesion = new GTextField(this, 345, 24, 272, 26, G4P.SCROLLBARS_NONE);
  NombreSesion.setText("Nombre de la sesión:");
  NombreSesion.setOpaque(false);
  NombreSesion.addEventHandler(this, "NombreSesione");
  NotasAdiocionales = new GTextArea(this, 758, 480, 218, 106, G4P.SCROLLBARS_NONE);
  NotasAdiocionales.setText("Notas adicionales:");
  NotasAdiocionales.setOpaque(true);
  NotasAdiocionales.addEventHandler(this, "NotasAdicionales_change1");
  ImagenRaton = new GImageButton(this, 665, 8, 100, 60, new String[] { "12.jpg", "12.jpg", "12.jpg" } );
  ImagenRaton.addEventHandler(this, "imgRaton_click1");
  TempBoton = new GImageButton(this, 16, 453, 43, 122, new String[] { "ter blanco.png", "ter rojo.png", "ter invertido.png" } );
  TempBoton.addEventHandler(this, "TempBoton_click1");
  Ciclo = new GImageButton(this, 292, 476, 86, 91, new String[] { "ciclo blanco.png", "ciclo cyan.png", "ciclo invertido.png" } );
  Ciclo.addEventHandler(this, "Ciclo_click1");
  ConectarUSB = new GImageButton(this, 24, 3, 40, 69, new String[] { "usb blanco.png", "usb azul.png", "usb azul oscuro.png" } );
  ConectarUSB.addEventHandler(this, "ConectarUSB_click1");
}

// Variable declarations 
// autogenerated do not edit
GButton SalirBoton; 
GButton buttonON; 
GButton OFFboton; 
GToggleGroup togGroup1; 
GToggleGroup togGroup2; 
GButton GuardarPNG; 
GTextField NombreSesion; 
GTextArea NotasAdiocionales; 
GImageButton ImagenRaton; 
GImageButton TempBoton; 
GImageButton Ciclo; 
GImageButton ConectarUSB;

Thank you very much for the help. :slight_smile:

1 Like

It looks like you’re drawing more items after you call saveFrame(). Anything you draw after you save the frame will not be included in the output file.

1 Like

saveFrame () is just before “exit” there is nothing after.

Captura

The code you posted contains elements after you call saveFrame():

If this is not representative of the code you’re running, please post a minimal reproducible example that shows your problem. Thanks!

I even have a saveFrame () before it is automatic, what is drawn after that saveFrame () is the graph grid, and that is saved in the screenshot, in fact even the normal buttons are saved, the only thing that doesn’t saved in the screenshot are the buttons / image that I have added from the G4P Tool.

The code is correct, it happens that I have the saveFrame () in two different places in the code, the first one is in that area that you indicate and the other is at the end, in the same way it is saved in the screenshot what It is drawn after the first saveFrame (), what is not saved in the screenshot are the buttons / image added with the G4P.

Can you post a minimal reproducible example that isolates the problem in a small program that we can run? A sketch that takes a screenshot of a single button would be good.

You’ll have better luck if you start with a simpler project. Use G4P to show a single button rather than posting your whole project. Good luck!

Ready, I did what he asked me, and the error is with the rectangle that I add behind the image / button, the thing is that I need that rectangle because otherwise when I print data but there is a rectangle behind, the data is overwritten in Image and looks very bad. So how could I make the saveFrame () function take a real screenshot of what is seen on the screen?

Code:

import g4p_controls.*;

public void setup(){
  size(200, 200, JAVA2D); //Tamaño de la ventana principal
  createGUI();
  customGUI();
}

public void draw(){
  rect(0, 0, 200, 200,1); //Rectángulo detrás del USB.
  fill(17,34,51);//Color del Texto arriba derecha. 
}
public void customGUI(){

}

void screenshot(){
  saveFrame( "Click"+"/"+day()+"-"+month()+"-"+year()+" a las "+hour()+"_"+minute() +" con "+ second()+"s"+ ".png") ; //dar nombre de fecha a los pantallazos
}

Gui:

public void button1_click1(GButton source, GEvent event) { 
  screenshot();
} 

public void imgButton1_click1(GImageButton source, GEvent event) { 
  
} 



// 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");
  button1 = new GButton(this, 64, 21, 80, 30);
  button1.setText("Save Screenshot");
  button1.addEventHandler(this, "button1_click1");
  imgButton1 = new GImageButton(this, 59, 72, 84, 103, new String[] { "usb blanco.png", "usb azul.png", "usb invertido.png" } );
  imgButton1.addEventHandler(this, "imgButton1_click1");
}

// Variable declarations 
// autogenerated do not edit
GButton button1; 
GImageButton imgButton1;
1 Like

Without the rectangle it looks good.

21-1-2020 a las 21_36 con 50s

But when I add the rectangle this happens when I do a screenshot.

21-1-2020 a las 21_40 con 18s

And when I complete the rectangle the image is no longer visible in the screenshot.
21-1-2020 a las 21_41 con 12s

1 Like

I will ask a new question only with the problem code, thanks for your advice.

Interesting, thank you for the example. I see the same behavior as you.

Paging @quark!

If it’s helpful, here is a shorter example program that demonstrates the same problem:

import g4p_controls.*;

public void setup() {
  size(200, 200);

  GButton button = new GButton(this, 75, 75, 100, 50, "Click me");
  button.addEventHandler(this, "buttonClicked");
}

public void draw() {
  fill(255, 0, 0);
  rect(25, 25, 100, 100);
}

public void buttonClicked(GButton source, GEvent event) { 
  saveFrame("###-button.png");
} 

void keyPressed() {
  save("###-key.png");
}

When I run this, I see the button displayed on top of the red square:

image

But when I save a screenshot, the red square is on top:

202-button

1 Like

Thanks for the sample code, I will try to delete the other post but I don’t know how to do it.

For future reference, you should just keep the conversation in one thread rather than posting a new thread. This thread contains the code in question and I’ve messaged Quark (the author of G4P) to take a look. Splitting your question between multiple posts makes it harder to follow everything.

In any case I’m sure Quark will help you when he sees this.

Thank you very much and sorry, I am new to all this.

No worries! You’ve got an interesting question, and I’m looking forward to seeing the answer myself.

1 Like

A solution:

import g4p_controls.*;
boolean takeScreenshot = false;
public void setup() {
  size(200, 200);

  GButton button = new GButton(this, 75, 75, 100, 50, "Click me");
  button.addEventHandler(this, "buttonClicked");
}

public void draw() {
  if(takeScreenshot) {
    save("screenshot.png");
    takeScreenshot = false;
  }
  
  background(255);
  fill(255, 0, 0);
  rect(25, 25, 100, 100);
}

public void buttonClicked(GButton source, GEvent event) { 
  takeScreenshot = true;
} 

The issue is that the gui gets drawn after the draw() method is called. So one way to solve this is to take the screenshot at the beginning of the next time draw() gets called, before drawing anything.

5 Likes

Absolutely correct :smile:

I assume you want the screenshot to include the G4P controls, I can think of several ways to do this but the solution by @hamoid is the neatest and best way to do it.

1 Like

If hamoid’s solution does what you want then please change the title to remove the delete request and mark it as the solution.

You might rename the discussion “How to include G4P controls with saveFrame” because the solution might help others. We don’t like to delete discussions that have answers especially if they solved the problem.

3 Likes