We are about to switch to a new forum software. Until then we have removed the registration on this forum.
The short form of my question is: How do I set a custom font for a PGraphics object in processing 3? I'm trying to migrate a complex sketch from 2 to 3, I recreated the issue in a much simpler program so we can isolate it and focus on it.
Processing 2 has no issues with PGraphics.textFont( PFont ) to set the font of a PGraphics object. Processing 3 throws a generic "NULL ptr exception" ( mind you neither the pg object nor the myfont object are null and the ttf font is correctly loaded from the data directory as it works perfectly in the main frame ( line 8 simply works ) ).
Am I missing some sort of initialization for my pg object? the textfont memeber of PGraphics is set to null and pg.textFont = myfont; creates more issues than it solves.
If you want to test this code simply use any ttf font place it in the data directory and change myfont = createFont("small_pixel.ttf", 10); from "small_pixel.ttf" to your file name.
PGraphics pg;
PFont myfont;
void setup() {
size(640, 360);
pg = createGraphics(400, 200);
myfont = createFont("small_pixel.ttf", 10);
textFont(myfont);
// The next line is the issue
pg.textFont(myfont);
}
void draw() {
fill(0, 12);
rect(0, 0, width, height);
fill(255);
noStroke();
text("Hello main frame", 20, 20);
pg.beginDraw();
pg.background(150,150,150);
pg.fill(255,255,255);
pg.textSize(12);
pg.text("Hello pGraphics", pg.width/2, pg.height/2);
pg.textAlign(CENTER,CENTER);
pg.noFill();
pg.stroke(255);
pg.endDraw();
// Draw the offscreen buffer to the screen with image()
image(pg, 120, 60);
}
Answers
Have you tried moving the
pg.textFont()
call to afterpg.beginDraw()
indraw()
? It's possible you need to beginDraw on the PGraphics before you can set the font!? At least, that's the only difference I can see from code I have that's working.Yep that was it, I would suggest adding this behavior change to the processing.core javadoc for the textFont() method. Just a final note I wanted to keep my textfont in the setup so instead of moving the pg.textFont(myfont); line I did this and everything seems to work:
Do you mean that in Processing 2
PGraphics.textFont()
did not requirePGraphics.beginDraw()
to be called first and in Processing 3 it is required?If you would please report this to the Processing Docs github repo, Issues:
In order:
Yes, processing 2 did not require that, ( this stricter approach might be "better" but it's not documented, so... not great.. )
Done: https://github.com/processing/processing-docs/issues/521
just a clarification: this also works in processing3:
it just seems like it should be initialized with createGraphics not beginDraw, different responsibility...
Why!? beginDraw() is documented to set up the default properties of a PGraphics object. While the documentation might be clarified, I think you were relying on an undocumented quirk in Processing 2.x and this is now behaving as intended and documented.
I kind of replied to that here: https://github.com/processing/processing-docs/issues/521
But basically it seems arbitrary as a behavior, the error it throws is very generic, and given the name of the method it does not make sense for
textFont()
to be inside thebeginDraw() endDraw()
block. On top of it, it can be outside as long as it's after thebeginDraw()
call.It's a set property method, it could check to see if the property has been initialized and if not at least throw an exception a bit more meaningful than "null pointer exception". That's really all I'm suggesting.
The behavior is not obvious, it's not documented in the
textFont()
docs and there is no way to know that I need to look for thebeginDraw()
to do the initializing as it's main responsibility should be to populate thePGraphics
object with content. ( at least in how I understood it, i now know it also sets the properties )I'm not arguing we should change anything( i understand it's a core object ) , just perhaps that error message.
I also find this counterintuitive -- or at least inconsistent with the general narrative of begin/end commands for beginners.
I would instead have expected that an operation would either only work inside a draw "begin/end" block or work both inside and outside a draw block.
I wouldn't expect something to: