How to Dynamically set PGraphics object size? (or workaround)

Hey guys.

New to the forum, I've been working on a project for a few days now and I'm having trouble trying to make GUI. I want to only have to render it once, as to maintain efficiency, and I'm using built in draw functions. I thought that the best way to do this would be to use a PGraphics object like so...

//Window int scWidth=800; int scHeight=480; int lat=4; int dpb=12; color [] colors = {#000000,#666666,#999999,#FFFFFF}; public class Location { int X; int Y; public Location(int tt, int tg) { X=tt; Y=tg; } public int getX( ) { return X; } public int getY( ) { return Y; } } Location cartesian = new Location( 3, 3 ); PGraphics drawGUI; public class GridGUI{ Location location; PGraphics GUI; public GridGUI(Location a, color [] colors){ location=a; GUI=createGraphics(30,30); //rendering of GUI goes here. Tiny example, I want to create the size of the gui in here. } public void showGUI(){ //wip, will just be simply be something like image(GUI, location.getX(), location.getY()); } public void getColor(){ //wip... its complicated... :) } } GridGUI defaultPalette= new GridGUI(cartesian, colors); void settings(){ size(scWidth,scHeight); } void setup(){ surface.setResizable(true); background(220); } void draw(){ stroke(0); fill(255); }

I've obviously taken a lot of the code out so let me know if you need the full thing (you shouldn't need it)

For whatever reason Processing doesn't seem to let you create a PGraphics object in the scope of a class. It gives a nullptr exception on the createGraphics line during definition of the class. Removing the line where it generates the initialization of the object does nothing.

Basically what I'd like to do is create a graphics object outside of setup so I can have a constructor in a class with its own PGraphics buffer.

My current workaround is to make a large PGraphics object and set its boundaries in setup() and to create a PImage in the class instead.

drawGUI=createGraphics(3840,2160); [not expecting anyone to make a GUI frame over 4k resolution]

anyways, each instance of the class would then have a PImage object instead that it copies from the 4k buffer after it's drawn to.

Is there any way to define a PGraphics object in a class or function other than setup()? I can't seem to do it without a nullptr exception. I'd report this as a bug if it's not intended because it's a much desired feature for several other parts of the program I'm working on but if it's intended to have the size and context of each PGraphics object defined in setup then I'd be open to other workarounds.

Answers

  • @JackWitherall --

    There is no particular reason that you can't have PGraphics in a class.

    However, as per the PGraphics reference and examples:

    The beginDraw() and endDraw() methods are necessary to set up the buffer and to finalize it.

    Your NullPointerException is happening the second you try to draw pixels into a non-existent buffer because you skipped beginDraw().

    Here is a working demo:

    /** PGraphics in a Class
     * 2016-11-10 Jeremy Douglass - Processing 3.2.1
     **/
    
    HasPGraphics hp;
    
    void setup(){
      size(200,200);
      hp = new HasPGraphics();
    }
    void draw(){
      image(hp.display(),0,0);
    }
    
    class HasPGraphics {
      PGraphics pg;
      HasPGraphics(){
        pg = createGraphics(200,200);
        pg.beginDraw();
          pg.ellipse(100,100,100,100);
        pg.endDraw();
      }
      PGraphics display(){
        return pg;
      }
    }
    
  • hmm... Your explanation didn't help me quite too much because I although I never used beginDraw() and endDraw() I never did any attempt in drawing to the buffer at all. I already knew about that requirement. What ended up fixing the code was when I moved the var.createGraphics(30,30); into a function. I tried it in setup(), I tried it in mouseClicked(), and I even tried it in draw().

    It seems like the only time that the code didn't run was when the function createGraphics() was called outside of a function.

    Why does that happen? surely that isn't intended behavior.

  • Thank you for helping me get my code running though. Very good answer. Thank you for the example.

  • edited November 2016

    @JackWitherell -- very glad it was helpful, and glad you figured the rest of it out and got it working.

    var.createGraphics

    I'm not sure what that means. createGraphics is a method of PApplet, and you aren't subclassing PApplet in your example, so I don't know what var is.

    when the function createGraphics() was called outside of a function

    Actually, I think in this case what is triggering your buffer problem is initializing objects outside of setup -- which is to say, before size() has been called for the first time and before the renderer has been chosen (bad!). Don't do this globally:

    Location cartesian = new Location( 3, 3 );
    GridGUI defaultPalette = new GridGUI(cartesian, colors);
    

    Instead, declare globally:

    Location cartesian;
    GridGUI defaultPalette;
    

    ...and initialize inside setup(), after size() has been called.:

    cartesian = new Location( 3, 3 );
    defaultPalette = new GridGUI(cartesian, colors);
    

    Also, as you can see in my demo, there is no problem with directly declaring a PGraphics globally and then initializing it in setup().

    Of course, you can initialize after setup as well, as you found!

  • Oh I completely get it now!

    real quick- sorry for being confusing. Var is a generic name I use for variables. It sounds a bit weird when referring to an object. I'll stop that. :)

    Thank you for your explanation. I'm not quite familiar with the way applets work within the java system, which is a pretty hefty part of the .createGraphics function.

    According to the createGraphics manual page in Processing's reference size definitely needs to be declared before even thinkg about using createGraphics. Just as the settings function (only used on rare occasions within processing) runs before the main graphics buffer is declared, code outside and in my case above any function is run before setup. This includes global variables within processing.

    Sorry that I keep talking, I just couldn't find it in google and I want anyone who is as stuck in the future to have as much a chance as fully understand this problem. :)

  • Great -- and thanks for sharing your explanation for future learners.

Sign In or Register to comment.