question about PGraphics

here's PGraphics reference example

PGraphics pg;

void setup() {
  size(100, 100);
  pg = createGraphics(40, 40);
}

void draw() {
  pg.beginDraw();
  pg.background(100);
  pg.stroke(255);
  pg.line(20, 20, mouseX, mouseY);
  pg.endDraw();
  image(pg, 9, 30); 
  image(pg, 51, 30);
}

BUT how to proceed if my code has many lines and i don't want to add pg. before each line? i tried to wrap up everything i need to as PGraphics in test() function, but it doesn't work that way... so how to do it?

PGraphics pg;

void setup() {
  size(100, 100);
  pg = createGraphics(40, 40);
}


void test() {

  background(100);
  stroke(255);
  line(20, 20, mouseX, mouseY);
}

void dipslaytest(float x, float y) {
  pg.beginDraw();
  test();
  pg.endDraw();
  image(pg, x, y);
}

void draw() {

  dipslaytest(9, 30);
  dipslaytest(51, 30);
}

Answers

  • edited August 2014 Answer ✓

    That's a very hackish question! Warning: complicated tech answers ahead... :-B
    See it that way, even Processing's canvas functions gotta use a reference w/ dot operator internally:
    https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java#L12039

    /** The PGraphics renderer associated with this PApplet */
    public PGraphics g; // #L259
    
    /** A leech graphics object that is echoing all events. */
    public PGraphics recorder; // #L321
    
    // #L12039: 
    public void line(float x1, float y1, float x2, float y2) {
      if (recorder != null)  recorder.line(x1, y1, x2, y2);
      g.line(x1, y1, x2, y2);
    }
    

    See? A simple line() needs to invoke a PGraphics object in order to draw in the canvas! No escape! :-&
    All class members (fields & methods) demand a reference in order to be reached out!
    But w/ 1 exception: If that reference is this, we can omit it. Compare these 2 examples:


    this.size(800, 600, JAVA2D);
    this.noLoop();
    this.background((color) this.random(#000000));
    

    size(800, 600, JAVA2D);
    noLoop();
    background((color) random(#000000));
    

    The only diff. is that in the 1st 1, this. was explicitly used. And in the 2nd 1 those were omitted! :(|)
    That is so b/c a Processing's sketch extends its PApplet class, inheriting all its members! \m/
    So their reference is this. However, Java is smart enough to spot that and hence no need to type them in!

    So, if you wanna avoid typing a reference + dot before each drawing method you gotta have a class which extends PGraphics. More precisely, some subclass of it, like PGraphicsJava2D.
    This way, those methods can be invoked w/o an explicit reference, b/c they'd be all this! *-:)

    Here's a link to an old thread whose OP wanted to modify PGraphics class in order to include custom methods:
    http://forum.processing.org/two/discussion/5238/creating-a-layer-class-that-extends-pgraphics

    A shorten version of it:

    /**
     * JAVA2D Subclass (v1.13)
     * by GoToLoop (2014/May)
     *
     * forum.processing.org/two/discussion/5238/
     * creating-a-layer-class-that-extends-pgraphics
     *
     * forum.processing.org/two/discussion/6884/
     * question-about-pgraphics
     */
    
    class Layer extends PGraphicsJava2D {
      Layer(int w, int h) {
        PApplet p = getEnclosingPApplet();
        initialize(w, h, p, p.dataPath(""));
        ignite();
      }
    
      void initialize(int w, int h, PApplet p, String s) {
        setParent(p);
        setPrimary(false);
        setPath(s);
        setSize(w, h);
      }
    
      void ignite() {
        beginDraw();
        smooth(4);
        fill(-1);
        stroke(0);
        endDraw();
      }
    
      protected PApplet getEnclosingPApplet() {
        try {
          return (PApplet) getClass()
            .getDeclaredField("this$0").get(this);
        }
    
        catch (ReflectiveOperationException cause) {
          throw new RuntimeException(cause);
        }
      }
    
      @ Override String toString() {
        return "Width: " + width + "\t Height: " + height
          + "\nPath:  " + path;
      }
    }
    

    Pay attention to ignite() method. None of those PGraphics methods needed an explicit reference!
    Now you just need to create your own tidy customized methods. good luck! %%-

  • Any "solution" you come up with is going to be way more expensive (in terms of maintainability) than just adding the references. How much time do you think you're going to save? 10 minutes?

  • edited August 2016 Answer ✓

    A more updated example: I did a Layer subclass called CustomPGraph in order to shorten it.
    So we can leave parent class Layer in a separate tab and CustomPGraph having its own custom methods.
    Pay attention to CustomPGraph's script() method. No explicit reference at all: :D

    Tab: "JAVA2D_Subclass.pde":


    /**
     * JAVA2D Subclass (v1.3)
     * by GoToLoop (2014/May)
     *
     * forum.processing.org/two/discussion/5238/
     * creating-a-layer-class-that-extends-pgraphics#Item_4
     *
     * forum.processing.org/two/discussion/6884/
     * question-about-pgraphics#Item_3
     */
    
    CustomPGraph pg;
    int w, h;
    
    void setup() {
      size(800, 600, JAVA2D);
      frameRate(1);
      smooth(4);
      clear();
    
      println( pg = new CustomPGraph(width*3 >> 2, height*3 >> 2) );
      w = pg.width; 
      h = pg.height;
    
      pg.strokeWeight(3);
    }
    
    void draw() {
      final color c = (color) random(#000000);
    
      frame.setTitle("Frame: " + frameCount
        + "\t\tColor: #" + hex(c, 6));
    
      set(width-w >> 1, height-h >> 1, pg.script(c));
    }
    
    final class CustomPGraph extends Layer {
      CustomPGraph(int w, int h) {
        super(w, h);
      }
    
      CustomPGraph script(color c) {
        background(c);
        fill(~c | ALPHA_MASK);
        ellipse(width>>1, height>>1, random(width), random(height));
    
        fill(#FF0000);
        beginShape(TRIANGLES);
        vertex(0, 0);
        vertex(100, 0);
        vertex(0, 100);
        endShape();
        endDraw();
    
        return this;
      }
    }
    


    Tab: "Layer.java":


    import processing.core.PApplet;
    import processing.core.PGraphicsJava2D;
    
    public class Layer extends PGraphicsJava2D {
      public Layer() {
      }
    
      public Layer(int w, int h) {
        PApplet p = getEnclosingPApplet();
        initialize(w, h, p, p.dataPath(""));
        ignite();
      }
    
      public Layer(int w, int h, PApplet p) {
        initialize(w, h, p, p.dataPath(""));
        ignite();
      }
    
      public Layer(int w, int h, PApplet p, String s) {
        initialize(w, h, p, s);
        ignite();
      }
    
      public void initialize(int w, int h, PApplet p, String s) {
        setParent(p);
        setPrimary(false);
        setPath(s);
        setSize(w, h);
      }
    
      public void ignite() {
        beginDraw();
        smooth(4);
        fill(-1);
        stroke(0);
        endDraw();
      }
    
      protected PApplet getEnclosingPApplet() {
        try {
          return (PApplet) getClass()
            .getDeclaredField("this$0").get(this);
        }
        catch (ReflectiveOperationException cause) {
          throw new RuntimeException(cause);
        }
      }
    
      @ Override public String toString() {
        return "Width: " + width + "\t Height: " + height
          + "\nPath:  " + path;
      }
    }
    

  • Answer ✓

    As you can see any solution to avoid using pg. is complex and probably unnecessary. KevinWorkman has said it all - tons of code to maintain just to avoid a little typing.

  • edited August 2014

    How much time do you think you're going to save? 10 minutes?

    As you can see any solution to avoid using pg. is complex and probably unnecessary.

    It's true the PGraphics' class replacement Layer is relatively complex w/ a buncha boilerplate code. [..]
    Its job is both replace function createGraphics() and allow us to enhance it w/ new methods of our own! =P~

    But it's also true that we can simply open a new tab in the IDE and move all that code outta our sight!
    We don't need to understand what it does. Just treat it as any other library! *-:)

    As an extra, class Layer is written in a way that it works both w/ ".pde" & ".java" suffixed tabs!
    That is, class Layer can freely be both an inner or a top class respectively! \m/

    Best course of action is make another subclass which extends Layer and place our reference-less scripts there.
    Just like I did in CustomPGraph! And we can also implement any new features for our custom PGraphics too! B-)

    Well, that's all folks! ~O)

  • Sorry, but no. This is not a good way to use inheritance, since you aren't actually changing the behavior of the parent class at all.

    Recommended reading: http://en.wikipedia.org/wiki/Composition_over_inheritance

    Telling a novice to extend PGraphics or some other class just to avoid typing 3 characters is not great advice. Programming involves typing. Three characters is not a lot of text, and more to the point, it's the correct approach here. Anything else is just getting the OP into some pretty horrible habits.

Sign In or Register to comment.