Multiple Window sketches

The information presented here is for G4P 4.0 and PS3, it does not apply to earlier versions.

The ability to create multiple window sketches is one of the most powerful features of G4P and this page describes how to create and use your own windows.

To handle multiple windows G4P has 2 classes they are

  • GWindow this class inherits from (extends) the processing.core.PApplet class so has all the functionality you would find in a single window sketch. G4P allows you to create windows using the JAVA2D, P2D or P3D renderers that look and feel just like the main sketch window.
  • GWinData in Processing it is common to talk about 'global variables' and although these are accessible to any windows you create it is not very flexible, especially if you have many windows. It would be better that each window has its own data. This class helps you do that.

In our sketch we can include a GWindow declaration statement with the statement

GWindow window;

The next stage would be to create the window, usually in the setup method. The statement to do that is

window =  GWindow.getWindow(this, "My Window", 100, 50, 480, 320, JAVA2D);

This function call has 7 parameters and the first one should always be this. The second one is the window title, this is followed by the x/y coordinates for the window position then the width and height of the window's drawing surface. The actual window will be larger to accomodate the frame border and title bar. The final parameter is the renderer type and must be either JAVA2D, P2D or P3D.

So now we have a window, but it is no use if we can't draw something on it the solution is to tell Processing what method will handle the drawing task. We do this by adding a draw handler

window.addDrawHandler(this, "windowDraw");

This code tells the GWindow object the name of the method to be used. So in this case it will look for a method called windowDraw that has 2 parameters of type PApplet and GWindata e.g.

public void windowDraw(PApplet app, GWinData data){
    app.background(255);
    app.strokeWeight(2);
    // draw black line to current mouse position
    app.stroke(0);
    app.line(app.width / 2, app.height/2, app.mouseX, app.mouseY);
  }
}

The app parameter is a reference to the GWindow object window and since GWindow extends PApplet it can be used to access all the methods available in PApplet e.g. stroke, fill, color etc.

The second parameter is a reference to a GWinData object but we have not created one yet so it will have the value null, this will be discussed later. Before that I want to discuss mouse and keyboard interaction.

Just as we added the draw handler we can do the same for the mouse and keyboard -

window.addMouseHandler(this, "windowMouse");
window.addKeyHandler(this, "windowKey");
The handlers would be
public void windowMouse(PApplet app, GWinData data, MouseEvent event) {

}

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


}

Notice that both these have an additional parameter event. The MouseEvent and KeyEvent classes are part of Processing and can be found in the processing.event package. It does mean that you have to determine the type of events yourself but that is a small price to pay for multiple windows :)

Since these methods are all in the main sketch they have access all the variables declared in the main sketch. In many cases this might not be a problem but it is not ideal situation. For instance the Mandelbrot example that comes with G4P can have dozens of windows each requiring a number of variables, matching variables to windows can be done but it would be better if the window had its own data.

The solution is to create a class that extends GWinData and put in the variables the window needs e.g.

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

So after creating the window add a the data object to the window.

window.addData(new MyData());

Now in our mouse habdler we can add some code to remember the last mouse click position

public void windowMouse(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;
    }
}

and in the draw handler we can use this data.

public void windowDraw(PApplet app, GWinData data){
    // Saves doing it for every variable in MyData class
    MyData myData = (MyData) data;
    app.background(255);
    app.strokeWeight(2);
    // Draw red line to last click position.
    app.stroke(255,0,0);
    app.line(app.width / 2, app.height/2, myData.lastClickX, myData.lastClickY);
    // draw black line to current mouse position
    app.stroke(0);
    app.line(app.width / 2, app.height/2, app.mouseX, app.mouseY);
  }
}

The only real difference from previous versions of G4P is the window creation and in the handler methods the type of the first parameter is PApplet.