Initialize subclass of PGraphics

I’m working in the Eclipse environment and am looking to create a new class (TGraphics) that extends PGraphics.
I want to do this so that I can polymorph the beginDraw() method to send an message to my event bus every time it’s called.

My problem is that I cannot cast the return of createGraphics() to a TGraphics object and I’m not sure why.
It has no problem casting to PGraphicsJava2D, which is a processing subclass of PGraphics, so why won’t it cast to mine? (TGraphics has absolutely no code aside from extending PGraphics)

The error I get is this:
java.lang.ClassCastException: class processing.awt.PGraphicsJava2D cannot be cast to class tAWT.TGraphics (processing.awt.PGraphicsJava2D and tAWT.TGraphics are in unnamed module of loader ‘app’)

I’ve copied and gutted the makeGraphics() method (called by createGraphics()) down to its critical code and will paste a copy of it below.

Any insight or suggestions would be much appreciated.
Thanks

protected PGraphics makeGraphics(int w, int h, String renderer, String path, boolean primary) 
	{
		try 
		{
			Class<?> rendererClass = Thread.currentThread().getContextClassLoader().loadClass(renderer);
			
			Constructor<?> constructor = rendererClass.getConstructor(new Class[] {});
			PGraphics pg = (PGraphics) constructor.newInstance();

			pg.setParent(this);
			pg.setPrimary(primary);
			if (path != null) 
			{
				pg.setPath(savePath(path));
			}

			pg.setSize(w, h);

			return pg;

		} catch (InvocationTargetException ite) {
			return null;
		} catch (ClassNotFoundException cnfe) {
			return null;
		} catch (Exception e) {
			return null;
		}
	}

This is my first time digging into the processing source code so I hope this helps. The problem you are facing is more of a Java problem though than a processing one.

By extending PGraphics you would have to replace the renderer implementations to inherit from your subclass(TGraphics) and not PGraphics, otherwise PGraphics2D (or any other renderer class) can’t be cast to TGraphics as it isn’t a subclass of it. You can extend an implementation of a renderer class and cast it though, see this example of extending PGraphics2D with a TGraphics2D class.

import processing.core.PApplet;
import processing.opengl.PGraphics2D;

import java.util.Random;

public class TGraphics2D extends PGraphics2D {

    private static Random rnd = new Random();

    public TGraphics2D createGraphics(PApplet applet, int w, int h) {
        return (TGraphics2D) applet.createGraphics(w, h, this.getClass().getName()); //pass class name to class loader seen in make graphics snippet you posted
    }

    public void beginDraw() {
        super.beginDraw();
        this.fill(rnd.nextFloat() * 255, rnd.nextFloat() * 175, rnd.nextFloat() * 255); //just here to show overriding
        //your other functionality goes here
    }
}

Then the sketch class

import processing.core.PApplet;

public class SketchOne extends PApplet {
    TGraphics2D extendedGraphics;
    int sketchWidth = 800, sketchHeight = 600;

    public void settings() {
        size(sketchWidth, sketchHeight, P2D); //sketch renderer should match with your extended renderer
    }

    public void setup() {
        extendedGraphics = new TGraphics2D().createGraphics(this, sketchWidth, sketchHeight);
    }

    public void draw() {
        extendedGraphics.beginDraw();

        extendedGraphics.background(0);
        extendedGraphics.ellipse(width / 2.0f, height / 2.0f, random(500), random(500));

        extendedGraphics.endDraw();

        image(extendedGraphics, 0,0, width, height);

    }

    public static void main(String[] args) {
        PApplet.main(new String[]{SketchOne.class.getName()});
    }
}

3 Likes

It worked!
I still don’t fully understand what’s going on under the hood but that’s likely because I need to keep developing my Java skills.
I’m going to keep digging through it and try to understand what’s happening.

Thank you so much for taking the time to put this solution together!
I very much appreciate it.