Using PApplet.runSketch to create multiple windows in a PS3 sketch.

I have been experimenting with PApplet.runSketch to create multiple windows with limited success.

My main question is :- Is it appropriate for a library, such as G4P, to use this method to create multiple windows in a PS3 sketch? If not what is?

In the following code I have been experimenting with the args argument to this method. Based on my research the code below should open the secondary window in the top left corner but it uses the default screen centre instead. Any thoughts?
EDIT this problem was solved thanks to GoToLoop's PS3 code below

EDIT this code has been corrected for PS3

// Main sketch (first) tab

void settings(){
  size(600, 200);  
}

void setup() {
  String[] args = {"--location=0,0", "Foo"};
  Foo sa = new Foo(320, 240);
  PApplet.runSketch(args, sa);
}

void draw() {
  background(0);
  ellipse(50, 50, 10, 10);
}     

// Foo.java tab

import processing.core.*;

public class Foo extends PApplet {

  private final int w, h;

  public Foo() {
    w = 200;
    h = 200;
  }

  public Foo(int w, int h) {
    this.w = w;
    this.h = h;
  }

  public void settings() {
    size(w, h);
  }

  public void draw() {
    background(255);
    fill(0);
    ellipse(100, 50, 10, 10);
  }
}

Answers

  • I guess it depends why you want to display multiple windows.

    If the window is for the library itself, I would assume you'd use the underlying Java code instead of relying on Processing.

  • edited September 2015

    I did some extra experiments based on my example code from:
    http://forum.Processing.org/two/discussion/11304/multiple-monitors-primary-dragable-secondary-fullscreen

    1st the Processing 1.5.1 version:

    /**
     * Multi-Monitor Sketch (v1.6)
     * by GoToLoop (2015/Jun/28)
     *
     * forum.Processing.org/two/discussion/11304/
     * multiple-monitors-primary-dragable-secondary-fullscreen
     *
     * forum.Processing.org/two/discussion/10937/multiple-sketches
     */
    
    void setup() {
      size(300, 300, JAVA2D);
      smooth();
      noLoop();
      frameRate(60);
      stroke(-1);
      strokeWeight(1.5);
    
      runSketch( new String[] { "--display=1",
                                "--location=0,0",
                                "--sketch-path=" + sketchPath,
                                "Projector" },
                 new ProjectorSketch() );
    
      println("Main's  sketchPath: \t\"" + sketchPath + "\"");
      println("Main's  dataPath: \t\"" + dataPath("") + "\"\n");
    }
    
    void draw() {
      background(0);
      line(0, 0, width, height);
    }
    
    class ProjectorSketch extends PApplet {
      void setup() {
        size(screen.width>>1, screen.height>>1, JAVA2D);
        smooth();
        //noLoop();
        frameRate(1);
        stroke(#FFFF00);
        strokeWeight(5);
    
        println("Inner's sketchPath: \t\"" + sketchPath("") + "\"");
        println("Inner's dataPath: \t\"" + dataPath("") + "\"\n");
      }
    
      void draw() {
        background((color) random(#000000));
        line(width, 0, 0, height);
    
        saveFrame( dataPath("screen-####.jpg") );
      }
    }
    

    And now Processing 2.2.1 version:

    /**
     * Multi-Monitor Sketch (v1.61)
     * by GoToLoop (2015/Jun/28)
     *
     * forum.Processing.org/two/discussion/11304/
     * multiple-monitors-primary-dragable-secondary-fullscreen
     *
     * forum.Processing.org/two/discussion/10937/multiple-sketches
     */
    
    void setup() {
      size(300, 300, JAVA2D);
      smooth(4);
      noLoop();
      frameRate(60);
      stroke(-1);
      strokeWeight(1.5);
    
      runSketch( new String[] { "--display=1",
                                "--location=0,0",
                                "--sketch-path=" + sketchPath,
                                "" },
                 new ProjectorSketch() );
    
      println("Main's  sketchPath: \t\"" + sketchPath + "\"");
      println("Main's  dataPath: \t\"" + dataPath("") + "\"\n");
    }
    
    void draw() {
      background(0);
      line(0, 0, width, height);
    }
    
    class ProjectorSketch extends PApplet {
      void setup() {
        size(displayWidth>>1, displayHeight>>1, JAVA2D);
        smooth(4);
        //noLoop();
        frameRate(1);
        stroke(#FFFF00);
        strokeWeight(5);
    
        println("Inner's sketchPath: \t\"" + sketchPath("") + "\"");
        println("Inner's dataPath: \t\"" + dataPath("") + "\"\n");
      }
    
      void draw() {
        background((color) random(#000000));
        line(width, 0, 0, height);
    
        saveFrame( dataPath("screen-####.jpg") );
      }
    }
    
  • edited August 2015

    But I couldn't make size() inside settings() to accept any variable in Processing 3.0b5!
    Be that some explicitly declared field initialized inside the constructor.
    Or relying on args[] passed from runSketch()! ~X(

    /**
     * Multi-Monitor Sketch (v1.6)
     * by GoToLoop (2015/Jun/28)
     *
     * forum.Processing.org/two/discussion/11304/
     * multiple-monitors-primary-dragable-secondary-fullscreen
     *
     * forum.Processing.org/two/discussion/10937/multiple-sketches
     */
    
    void setup() {
      size(300, 300, JAVA2D);
      smooth(4);
      noLoop();
      frameRate(60);
      stroke(-1);
      strokeWeight(1.5);
    
      runSketch( new String[] { "--display=1",
                                "--location=0,0",
                                "--sketch-path=" + sketchPath(""),
                                "Projector",
                                str(displayWidth), str(displayHeight) },
                 new ProjectorSketch(displayWidth, displayHeight) );
    
      println("Main's  sketchPath: \t\"" + sketchPath("") + "\"");
      println("Main's  dataPath: \t\"" + dataPath("") + "\"\n");
    }
    
    void draw() {
      background(0);
      line(0, 0, width, height);
    }
    
    class ProjectorSketch extends PApplet {
      int w, h, aaa;
    
      ProjectorSketch(int ww, int hh) {
        w = ww;
        h = hh;
      }
    
      void setting() {
        size(aaa = w>>1, h>>1, JAVA2D);
        smooth(4);
      }
    
      void setup() {
        println(aaa, w, width);  // 0 1920 100
        //noLoop();
        frameRate(1);
        stroke(#FFFF00);
        strokeWeight(5);
    
        println("Inner's sketchPath: \t\"" + sketchPath("") + "\"");
        println("Inner's dataPath: \t\"" + dataPath("") + "\"\n");
      }
    
      void draw() {
        background((color) random(#000000));
        line(width, 0, 0, height);
    
        saveFrame( dataPath("screen-####.jpg") );
      }
    }
    
  • edited August 2015
    • As you can see above, I try to assign w>>1 to field aaa.
    • But when printing it within setup(), it's still 0! @-)
    • I thought settings() would run before setup() or not? :-??
    • Dunno what kinda voodoo is going on, but size(aaa = w>>1, h>>1, JAVA2D);
      ends up as width = 100 & height = 100! :-&
    • Here's the resultant ".java" file:

    import processing.core.*; 
    import processing.data.*; 
    import processing.event.*; 
    import processing.opengl.*; 
    
    import java.util.HashMap; 
    import java.util.ArrayList; 
    import java.io.File; 
    import java.io.BufferedReader; 
    import java.io.PrintWriter; 
    import java.io.InputStream; 
    import java.io.OutputStream; 
    import java.io.IOException; 
    
    public class Multi_Monitor extends PApplet {
    
    /**
     * Multi-Monitor Sketch (v1.6)
     * by GoToLoop (2015/Jun/28)
     *
     * forum.Processing.org/two/discussion/11304/
     * multiple-monitors-primary-dragable-secondary-fullscreen
     *
     * forum.Processing.org/two/discussion/10937/multiple-sketches
     */
    
    public void setup() {
    
    
      noLoop();
      frameRate(60);
      stroke(-1);
      strokeWeight(1.5f);
    
      runSketch( new String[] { "--display=1",
                                "--location=0,0",
                                "--sketch-path=" + sketchPath(""),
                                "Projector",
                                str(displayWidth), str(displayHeight) },
                 new ProjectorSketch(displayWidth, displayHeight) );
    
      println("Main's  sketchPath: \t\"" + sketchPath("") + "\"");
      println("Main's  dataPath: \t\"" + dataPath("") + "\"\n");
    }
    
    public void draw() {
      background(0);
      line(0, 0, width, height);
    }
    
    class ProjectorSketch extends PApplet {
      int w, h, aaa;
    
      ProjectorSketch(int ww, int hh) {
        w = ww;
        h = hh;
      }
    
      public void setting() {
        size(aaa = w>>1, h>>1, JAVA2D);
        smooth(4);
      }
    
      public void setup() {
        println(aaa, w, width);  // 0 1920 100
    
        //noLoop();
        frameRate(1);
        stroke(0xffFFFF00);
        strokeWeight(5);
    
        println("Inner's sketchPath: \t\"" + sketchPath("") + "\"");
        println("Inner's dataPath: \t\"" + dataPath("") + "\"\n");
      }
    
      public void draw() {
        background((int) random(0xff000000));
        line(width, 0, 0, height);
    
        saveFrame( dataPath("screen-####.jpg") );
      }
    }
      public void settings() {  size(300, 300, JAVA2D);  smooth(4); }
      static public void main(String[] passedArgs) {
        String[] appletArgs = new String[] { "Multi_Monitor" };
        if (passedArgs != null) {
          PApplet.main(concat(appletArgs, passedArgs));
        } else {
          PApplet.main(appletArgs);
        }
      }
    }
    
  • edited February 2016 Answer ✓
    • Oh, that was stupid! Due to lack of experience (just installed Processing 3 yesterday!), I've typed in setting() instead of settings()! b-(
    • Nevertheless, here's the fixed code w/ "--location=0,0" working alright.
    • Although "--location=0,0" was already functioning even w/ mistyped settings() btW! :P

    P.S.: I had to create an explicit settings() for the main sketch for v2.1 b/c PDE's pre-processor didn't!
    Perhaps b/c ProjectorSketch nested class already had settings() in it! 8-}

    /**
     * Multi-Monitor Sketch (v2.11)
     * by GoToLoop (2015/Aug/31)
     *
     * forum.Processing.org/two/discussion/12319/
     * using-papplet-runsketch-to-create-multiple-windows-in-a-sketch
     * 
     * forum.Processing.org/two/discussion/11304/
     * multiple-monitors-primary-dragable-secondary-fullscreen
     *
     * forum.Processing.org/two/discussion/10937/multiple-sketches
     */
    
    void settings() {
      size(300, 300, JAVA2D);
      smooth(4);
    }
    
    void setup() {
      noLoop();
      frameRate(60);
      stroke(-1);
      strokeWeight(1.5);
    
      runSketch( new String[] { "--display=1",
                                "--location=0,0",
                                "--sketch-path=" + sketchPath(""),
                                "" },
                 new ProjectorSketch() );
    
      println("Main's  sketchPath: \t\"" + sketchPath("") + "\"");
      println("Main's  dataPath: \t\"" + dataPath("") + "\"\n");
    }
    
    void draw() {
      background(0);
      line(0, 0, width, height);
    }
    
    class ProjectorSketch extends PApplet {
      void settings() {
        size(displayWidth>>1, displayHeight>>1, JAVA2D);
        smooth(4);
      }
    
      void setup() {
        frameRate(1);
        stroke(#FFFF00);
        strokeWeight(5);
    
        println("Inner's sketchPath: \t\"" + sketchPath("") + "\"");
        println("Inner's dataPath: \t\"" + dataPath("") + "\"\n");
      }
    
      void draw() {
        background((color) random(#000000));
        line(width, 0, 0, height);
    
        saveFrame( dataPath("screen-####.jpg") );
      }
    }
    
  • @KevinWorkman

    I guess it depends why you want to display multiple windows.

    Sorry didn't make myself clear. I am trying to make G4P compatible with PS3. G4P provides an easy to use GUI with a wide variety of controls incl buttons, sliders, droplists, textfields and many more. One of the more powerful features of G4P was support for additional windows, thus enabling the user/sketcher to easily create multi-window sketches. These secondary windows could be used to hold other G4P controls to create 'control windows' or simply for graphic display. For instance the Mandelbrot example that comes with G4P creates a new window for every view on the set, when trying it out I must have had 20-30 windows open.

    PS1 & 2 didn't have any native support for multiple windows so the G4P code had to be pretty complex to get it to work smoothly. This is why there will not be a single version of G4P that works in both PS2 & PS3

    The reason that I asked the question

    Is it appropriate for a library, such as G4P, to use this method to create multiple windows in a sketch? If not what is?

    is because PS3 appears to offer some limited support for multiple windows using the runSketch method, but I don't think this is what the PS developers had in mind so I hope they will respond and provide more information on this topic.

    @GoToLoop

    Thanks for the examples unfortunately again I didn't make myself clear. I am only interested in PS3 sketches so although your code was interesting only the last post was useful. Very useful as it turns out because it highlighted a couple of mistakes in my code. First I didn't include the settings method and secondly the order of the arguments was wrong.

    I have gone back and corrected the code above and changed the title to reflect that I am interested in PS3.

    Thanks guys I think I will raise another question aimed primarily at the developers of PS3 to get more info about this topic.

  • edited August 2015

    I am only interested in PS3...

    The path you're exploring right now, runSketch(), is compatible w/ Processing 1 and forward!
    I'm just re-highlighting that fact to you! O:-)
    I was only able to help you this time b/c I've been using main() & runSketch() since previous forum! :P

    ... so although your code was interesting only the last post was useful.

    All of those 3 versions (ea. 1 for ea. Processing series) are very similar to each other.
    Only main diff. is that for Processing 3, we've got that "pesky" setup() new "cousin": settings()! :O)

  • edited August 2015

    PS1 & 2 didn't have any native support for multiple windows...

    Neither Processing 3! No matter which Processing version, multiple instances is an undocumented "feature", made possible via PApplet's main() & runSketch() static methods. :-B

    ... is because PS3 appears to offer some limited support for multiple windows using the runSketch method, ...

    Not Processing 3, but Processing 1 has always had limited support for multi windows via runSketch()! :-\"

  • G4P provided sophisticated multiple window support (for PS1 & PS2) using documented Processing methods only. This was possible because PApplet inherited from a windowed component so I was not reliant on runSketch. With PS3 this is not the case so I am forced to look at alternatives such as runSketch.

    All thus talk about PS1 and PS2, although interesting, does not help me find a way of updating G4P for Processing 3. Unfortunately runSketch doesn't look like it will give me the level of control I have at the moment with PS2 but I havn't given up on it yet.

  • edited September 2015

    G4P provided sophisticated multiple window support (for PS1 & PS2) using documented Processing methods only.
    This was possible because PApplet inherited from a windowed component...

    • AFAIK, Processing has never "officially condoned" any usage of its "innards" implementations.
    • In their PoV, relying on the fact PApplet was a Java's AWT Applet or Component was considered "undocumented" implementation detail!
    • In this forum, I was the only 1 who promoted the relying on main() or runSketch() to achieve multiple instances/windows.
    • Others either relied on making a class extending Frame or used some other 3rd-party library which did almost the same.
  • edited September 2015

    Unfortunately runSketch() doesn't look like it will give me the level of control I have at...

    • I'm also in the dark about which level of control you're seeking out.
    • Indeed runSketch() merely "ignites" some PApplet instance.
    • Thus creating 1 "canvas", be it a Frame or now a PSurface.
    • Plus the "Animation" Thread which continually calls back draw() after dealing w/ setup().
    • And now w/ settings() as well for Processing 3.
  • edited January 2016

    All thus talk about PS1 and PS2, although interesting, does not help me find a way of updating G4P for Processing 3.

    • If you decide on runSketch(), the "solution" is practically compatible across Processing versions!
    • Since runSketch() exists since Processing 1 and barely changed its internal implementation across versions!
    • However, if you're seeking to explore PSurface instead, of course it'd be compatible w/ P3 only! >-)
  • edited September 2015

    Thanks for the replies,.

    The problem I experienced with the args parameter to runSketch to set the window location was solved based on the Accepted Answer.

    I still need to do more research and experiments with runSketch to see the extent of what is possible.

  • I know this is an old post but I just wanted to say thanks for the solution to the problem I was having with incorporating a robot arm sim into the G4P GUI to control the arm. Was struggling with creating a second window using P3D or OpenGL and no joy - spent hours/days. Your solution had it working within a few minutes. Only error I am getting is the following:

    Unknown cursor type: 0 Unknown cursor type: 12

    Error gets thrown when I start the sketch but everything remains operational. Any ideas would be appreciated. No other messages appear.

    Thanks again. Mike

  • There was a problem with cursor in early releases of PS3 it was fixed in later releases. Don't if that was the cause of your particular problem.

  • Hi @quark thanks for the info. By the way I did an instructable on the robot arm and gui you an @GoToLoop helped me with. Gave both of you all credit, Thanks again.

  • Glad I could help and thanks for giving credit, much appreciated.

  • edited February 2016

    Hi, This is an important question to me too, the multiple window handling. I have some Processing relying software with uses 2 views on different windows. I had it solved with the old schema JFrame with added PApplets.

    Thanks to this post I'm able to swtich to PApplet.runSketch and no JFrames but there are some issues I cannot make work: 1) When I have 2+ PApplets running with runSketch and close one, all of them close (does not happen when, e.g. minimizing) 2) How do I change the window name? That was done in the JFrame and I cannot see any arg in runSketch for that 3) Related to 1, how to I replace a running PApplet with another one? This is not so important as I can just change the view without replacing.

    In the end, the question I guess it's: "to what extent runSketch replaces JFrame". One expects it to be fully, or it should not have been removed as an option.

    Very insightful thread anyways, thanks!

  • edited February 2016

    It does not replace JFrame rather runSketch will create the JFrame for you but only for JAVA2D renderer. Using runSketch with P2D and P3D creates an OpenGL window rather than a JFrame. Whichever type of window is created clicking on the red cross terminates the application so closes ALL open windows. Processing has done this by adding its own WindowAdapter(s) the solution is to remove them and add your own, or in the case of JFrame change the defaultActionOnClose

    You can look at the G4P library source code for GWindow and its subclasses to see how I overcame these issues.

  • Ok, understood, thanks quark! However, I had to dig more than expected/desired into Processing code for all this Processing 3 update with different windows. Actually, to get into the JFrame and change the defaultAction is not working. With this change:

    ((JFrame)((SmoothCanvas)myPApplet.getSurface().getNative()).getFrame()).setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

    it keeps exiting. Actually, the default behavior is HIDE_ON_CLOSE, and it also exits the whole application.

  • I added a WindowListener and actually enters in the Activated and Opened event handlers, but not in Closed or Deactivated! Quite strange...

    ((JFrame)((SmoothCanvas)myPApplet.getSurface().getNative()).getFrame()).addWindowListener(new MyWindowListener());

  • WindowAdapters are addative so you need to remove the existing ones first.

  • Wohooo! Worked! Bowing after you again quark. I always had assumed Listeners were unique. In case someone might find the code helpful, these two lines are enough to make PApplets 'hide on close' instead of exiting the whole app:

    WindowListener wl=((JFrame)((SmoothCanvas)myPApplet.getSurface().getNative()).getFrame()).getWindowListeners()[0];
    ((JFrame)((SmoothCanvas)myPApplet.getSurface().getNative()).getFrame()).removeWindowListener(wl);
    
  • edited February 2016

    Hi efialto

    Are you saying that just using those two lines of code you are able to get the PApplet.runSketch to hide on close. I been going nuts over trying to figure it out especially since I am very JAVA impaired. Will you be willing to share exactly how you accomplished it. Where exactly do you put the windowlistener in the PApplet. I tried a couple of places and it complained about SmoothCanvas or too many {, etc.

    This would temporarily solve my other issue that I posted: https://forum.processing.org/two/discussion/15095/g4p-second-window-how-to-include-gwoptics-library-in-second-window#latest

    Thanks awful much Mike

  • edited February 2016

    @CyberMerln, here's a more refined tweaked version of @efialto's solution: :ar!

    static final void removeExitEvent(final PSurface surf) {
      final java.awt.Window win
        = ((processing.awt.PSurfaceAWT.SmoothCanvas) surf.getNative()).getFrame();
    
      for (final java.awt.event.WindowListener evt : win.getWindowListeners())
        win.removeWindowListener(evt);
    }
    

    Also, I've redone my previous "Multi-Monitor Sketch" example to include removeExitEvent() too: :bz

    /**
     * Multi-Monitor Sketch (v2.21)
     * by GoToLoop (2015/Jun/28)
     *
     * forum.Processing.org/two/discussion/12319/
     * using-papplet-runsketch-to-create-multiple-windows-in-a-sketch
     * 
     * forum.Processing.org/two/discussion/11304/
     * multiple-monitors-primary-dragable-secondary-fullscreen
     *
     * forum.Processing.org/two/discussion/10937/multiple-sketches
     */
    
    ProjectorSketch projector;
    
    void settings() {
      size(300, 300, JAVA2D);
      smooth(4);
    
      println("Main's  sketchPath: \t\"" + sketchPath("") + "\"");
      println("Main's  dataPath: \t\"" + dataPath("") + "\"\n");
    }
    
    void setup() {
      noLoop();
      frameRate(60);
      stroke(-1);
      strokeWeight(1.5);
    
      runSketch( new String[] {
        "--display=1", 
        "--location=" + (displayWidth>>2) + ',' + (displayHeight>>3), 
        "--sketch-path=" + sketchPath(""), 
        "" }
        , projector = new ProjectorSketch() );
    }
    
    void draw() {
      background(0);
      line(0, 0, width, height);
    }
    
    void mousePressed() {
      projector.getSurface().setVisible(true);
    }
    
    static final void removeExitEvent(final PSurface surf) {
      final java.awt.Window win
        = ((processing.awt.PSurfaceAWT.SmoothCanvas) surf.getNative()).getFrame();
    
      for (final java.awt.event.WindowListener evt : win.getWindowListeners())
        win.removeWindowListener(evt);
    }
    
    class ProjectorSketch extends PApplet {
      void settings() {
        size(displayWidth>>1, displayHeight>>1, JAVA2D);
        smooth(4);
    
        println("Inner's sketchPath: \t\"" + sketchPath("") + "\"");
        println("Inner's dataPath: \t\"" + dataPath("") + "\"\n");
      }
    
      void setup() {
        removeExitEvent(getSurface());
    
        frameRate(1);
        stroke(#FFFF00);
        strokeWeight(5);
      }
    
      void draw() {
        background((color) random(#000000));
        line(width, 0, 0, height);
    
        saveFrame( dataPath("screen-####.jpg") );
      }
    
      @ Override void exit() {
      }
    }
    
  • edited February 2016

    @GoToLoop: You are absolutely great for putting this together. Can not tell you how much I appreciate it. Just tried it and it works like a charm.

    Thanks again. Mike

  • edited February 2016

    Nice explanation GoToLoop! Glad it was helpful for CyberMerln :)

Sign In or Register to comment.