1

I'm currently trying to develop a class for Processing library developers that is supposed to allow them to access the PApplet generated by Processing. I already asked this question on the Processing with no one being able to provide a real solutions.

I eventually managed to come up with this code that seems to work just fine for the JAVA2D renderer. (If it's requested I will send this code)

However for the P2D and P3D renderers this code doesn't work. I found the following reason for that:

P2D and P3D use JOGL (Java OpenGL) and it defines it's window type from scratch making java.awt.Window.getWindows() not detect this window. If I were able to find that window I would already have a plan on finding the PApplet.

How can I find all active JOGL windows in a similar manner to java.awt.Window.getWindows()?

Edit: The link to the entry in the Processing Forum: https://discourse.processing.org/t/get-the-current-instance-of-papplet-from-a-library/36925

The code that only works with the JAVA2D renderer:

import processing.awt.*;
import processing.core.*;

import javax.swing.*;
import java.awt.*;
import java.lang.reflect.*;
/**This class finds the active PApplet (Processing program)*/
public class PAppletFinder{
/**This class takes the contents of the window and pieces together the PApplet
 * @return PApplet of the current sketch.
 * @param c contents of the Processing window (must be a SmoothCanvas)*/
public static PApplet get(Component c) {
  PSurfaceAWT.SmoothCanvas sc=(PSurfaceAWT.SmoothCanvas) c;
  try {
    PSurfaceAWT psa=(PSurfaceAWT) get(sc,"this$0",sc.getClass());
    PApplet prg=(PApplet) get((PSurfaceNone)psa,"sketch",PSurfaceNone.class);
    return prg;
  }
  catch(Exception e) {
    e.printStackTrace();
  }
  return null;
}

public static PApplet foundPapplet=null;
/**The main method to be used when using the PAppletFinder*/
public static PApplet find() {
    if(foundPapplet==null) foundPapplet=findFromWindow();
    return foundPapplet;
}

/**This looks out for windows and gives the contents of the right one to the get method
 * @return PApplet of the current sketch.*/
public static PApplet findFromWindow() {
  JFrame mainWindow=null;
  java.awt.Window win[]=java.awt.Window.getWindows();
  for (int i=0; i<win.length&&mainWindow==null; i++) if (win[i] instanceof JFrame) mainWindow=(JFrame) win[i];

  Component c=mainWindow.getContentPane().getComponents()[0];
  return get(c);
}
/**This is used to get the this$0 field of the SmoothCanvas
 * Directly searching for the field didn't work. However for some reason
 * looking through all the fields does the trick.
 * @return Object value of a field
 * @param j the Object from which the value is taken
 * @param target name of the field*/
public static Object get(Object j,String target,Class<?> ref) {
    Field[] field_=ref.getDeclaredFields();
    for(int i=0;i<field_.length;i++) {
        field_[i].setAccessible(true);
        try {
            if(field_[i].getName().equals(target)) return field_[i].get(j);
            } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
return null;
}
}

This code works only in JAVA2D as processing uses JOGL windows with any other renderer. JAVA2D however uses JFrames which are a subclass of java.awt.Window and are therefore found by Window.getWindows().

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • It would help if you link to other question and add code you've tried. – DuncG Jul 02 '22 at 11:01
  • 1
    I added the current code that only works with JAVA2D as well as a link to the forum in an edit! Hope that helps! – NumericPrime Jul 02 '22 at 11:11
  • +1 for posting the code and forum post. Reading through the post I still don't understand why is your Processing library trying get instances of PApplets instead of the PApplets passing a reference to themselves (as most typical [Processing libraries do](https://github.com/processing/processing-library-template/blob/master/src/template/library/HelloLibrary.java#L34)). What is the end goal of your library and why is is the extra effort dynamically finding PApplets necessary ? – George Profenza Jul 02 '22 at 20:59
  • I am trying to use this to be abe to use static blocks in my library. And if I needed to provide the PApplet to a seperate class I would have to be very careful not to load any other classes that use the PApplet before it has been given by the user. Another possible approach would be combining 3 approaches. First look if the user has provided a PApplet. Second look up if a JFrame was generated. Third catch the old Thread in an infinite loop and restart the program in another thread with a known PApplet. – NumericPrime Jul 03 '22 at 06:23
  • @NumericPrime Processing uses NewtCanvasAWT in PSurfaceJOGL. I hope it helps. – gouessej Jul 06 '22 at 11:20

0 Answers0