Closing a second window

I want to be able to create a second window. The problem is I want the user to be able to close the second window, but doing so closes both the second and main frame. Is there a way I can prevent this?

PWindow win;

public void settings() {
  size(320, 240);
}

void setup() { 
  win = new PWindow();
}

void draw() {
  background(255, 0, 0);
  fill(255);
  rect(10, 10, frameCount, 10);
}

void mousePressed() {
  println("mousePressed in primary window");
} 

class PWindow extends PApplet {
  PWindow() {
    super();
    PApplet.runSketch(new String[] {this.getClass().getSimpleName()}, this);
  }

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

  void setup() {
    background(150);
  }

  void draw() {
    ellipse(random(width), random(height), random(50), random(50));
  }

  void mousePressed() {
    println("mousePressed in secondary window");
  }
}
2 Likes

This did the trick for me:


PWindow win;

public void settings() {
  size(320, 240);
}

void setup() { 
  surface.setLocation(20,20);
  win = new PWindow();
}

void draw() {
  background(255, 0, 0);
  fill(255);
  rect(10, 10, frameCount, 10);
}

void mousePressed() {
  println("mousePressed in primary window");
  if(win == null) win = new PWindow();
} 

class PWindow extends PApplet {
  PWindow() {
    super();
    PApplet.runSketch(new String[] {this.getClass().getSimpleName()}, this);
  }

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

  void setup() {
    background(150);
  }

  void draw() {
    ellipse(random(width), random(height), random(50), random(50));
  }

  void mousePressed() {
    println("mousePressed in secondary window");
  }
  
  void exit()
  {
    dispose();
    win = null;
  }
}

Clicking in the first window when the second is closed will also open a new secondary window.

1 Like

Above link gives the example SetDefaultCloseEvent sketch, which uses jogamp.newt.Window.setDefaultCloseOperation() to set a default close policy.

Actually, what is passed to setDefaultCloseOperation() is either the enums from com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode:

http://JogAmp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/nativewindow/WindowClosingProtocol.WindowClosingMode.html

Or the constants from interface javax.swing.WindowConstants:

https://Docs.Oracle.com/javase/10/docs/api/javax/swing/WindowConstants.html

Depending on the result of PGraphics::isGL() method. :face_with_monocle:

1 Like

Wouldn’t that prevent the user from closing the second window?

https://Docs.Oracle.com/javase/tutorial/uiswing/components/frame.html#windowevents

Ah, I get it now. It makes the window invisible, and pauses the sketch but it can be made visible again easily.

OP is essentially running two PApplets on the same JVM. My method terminates the secondary sketch but keeps the JVM open so the primary one can stay running.

So OP has the choice - either terminate one sketch entirely or keep it invisibly running and call it back fast when needed.

This is the code I came up with. There appears to be an issue when you close the primary sketch while the secondary sketch is still running, it crashes with the error “ThreadDeath”.

PWindow win;

public void settings() {
  size(320, 240);
}

void setup() { 
  surface.setLocation(20, 20);
  win = new PWindow();
}

void draw() {
  background(255, 0, 0);
  fill(255);
  rect(10, 10, frameCount, 10);
}

void mousePressed() {
  println("mousePressed in primary window");
  win.makeVisible();
} 



class PWindow extends PApplet {
  static final String RENDERER = P3D;
  PWindow() {
    super();
    PApplet.runSketch(new String[] {this.getClass().getSimpleName()}, this);
  }

  void settings() {
    size(500, 200, RENDERER);
  }

  void setup() {
    background(150);
    setDefaultClosePolicy(this, false);
  }

  void draw() {
    ellipse(random(width), random(height), random(50), random(50));
    println("running!", frameCount);
  }

  void mousePressed() {
    println("mousePressed in secondary window");
  }

  void exit()
  {
    dispose();
    win = null;
  }

  final void setDefaultClosePolicy(PApplet pa, boolean keepOpen) {
    final Object surf = pa.getSurface().getNative();
    final PGraphics canvas = pa.getGraphics();

    if (canvas.isGL()) {
      final com.jogamp.newt.Window w = (com.jogamp.newt.Window) surf;

      for (com.jogamp.newt.event.WindowListener wl : w.getWindowListeners())
        if (wl.toString().startsWith("processing.opengl.PSurfaceJOGL"))
          w.removeWindowListener(wl); 

      w.setDefaultCloseOperation(keepOpen?
        com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode
        .DO_NOTHING_ON_CLOSE :
        com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode
        .DISPOSE_ON_CLOSE);
    } else if (canvas instanceof processing.awt.PGraphicsJava2D) {
      final javax.swing.JFrame f = (javax.swing.JFrame)
        ((processing.awt.PSurfaceAWT.SmoothCanvas) surf).getFrame(); 

      for (java.awt.event.WindowListener wl : f.getWindowListeners())
        if (wl.toString().startsWith("processing.awt.PSurfaceAWT"))
          f.removeWindowListener(wl);

      f.setDefaultCloseOperation(keepOpen?
        f.DO_NOTHING_ON_CLOSE : f.DISPOSE_ON_CLOSE);
    }
  }
  
  public void makeVisible()
  {
    surface.setVisible(true);

  }
}
1 Like

For my application hiding the second window is preferred to terminating it, thanks guys

I’m also running into an issue where I want to apply a shader filter to both windows.
Both are set to use P2D. The second window sporadically crashes with errors when trying to do things like filter(blur) using the blur shader from the example /topics/shader/blurfilter

That PWindow::exit() method is never called back.
Instead, move that exit() to the main sketch PApplet in order to avoid that “ThreadDeath”:

@Override void exit() {
  win.dispose();
  super.exit();
}
2 Likes

Never mutate a PApplet’s PGraphics main canvas outside its own “Animation Thread”! :japanese_goblin:

I am doing it inside the new PApplet’s draw(){}, is that not the right location?

Yes, for its own main canvas… :face_with_raised_eyebrow:

However, if you try to mutate the other PApplet’s main canvas from there, it’s gonna crash! :ghost:

Here is my project, kind of in an early development stage right now. The idea is you left click to select a color from the spritesheet(or group of squares on the left), and rightclick to replace that color with whatever color is under the mouse pointer.

I’m trying to apply my PShader called highlight to both frames.

If you run the program, toggle the box labeled highlight, and left click on the spritesheet or the colored squares on the left, you’ll see my shader highlight the pixels and it all works fine.

Then if you click the histogram button, it opens the new window, and things get screwy. White and black random rectangles and sometimes GL errors. The filter is applied to the new window on line 53 of histogram.pde. If highlight is disabled, it works fine.

Usually but not always the error is GLException: array vertex_buffer_object must be bound to call this method

So basically you’re invoking filter(), passing the PShader loaded & created by the main PApplet on the canvas of the 2nd PApplet.

I know close to nothing about “.glsl” files, but is it feasible for each PApplet to have its own PShader of that same “.glsl” file?

If not, maybe create an extra PGraphics on the 1st PApplet.
But exclusively use that PGraphics on the 2nd PApplet.
Perhaps then you can call filter() over that PGraphics inside the 2nd PApplet.

When i add super.exit to second PApplet it close both Windows…

Please show your code or a minimum version demonstrating your approach.

Kf

1 Like

This is where the question was resolved. @kfrajer

1 Like