I might be a bit over my head, apologies for the semi-long sketch and wall-of-text. I’m really puzzled by this!
I have a sketch with a PDF export that works great on it’s own, but that just saves a file in the sketch folder. So I wanted to add a file selector (selectOutput), but that turned out to be not so easy…
I’ve kind of narrowed it down (and kind of not). I found a work-around of sorts and made this small (well, small-ish) stand-alone sketch to demonstrate. It works some, maybe most of the time but not always. Not to mention that this work-around doesn’t work at all in my main sketch that I want to use it in.
The main thing to look at here is in the mouseClicked() function, and the two exportToPDF() functions.
(In my main sketch I don’t use mouseClicked(), nor have these button classes like here, so there’s a few differences).
In short, the work-around was to create a dummy PDF file before calling selectOutput, and then make the real PDF file. Otherwise I’d always get a NullPointerException (and usually several lines of errors or warnings). I still get the NPE some of the time.
If I cancel out of the file dialog, I also get several lines of warnings but the sketch continues.
I suspected some of this could be due to the path name string containing the backslash character, which was not escaped(\\), but it didn’t matter if I used the file path at all.
Hopefully someone have some idea what’s going on, or a fix… Maybe there’s something I’m completely ignorant of.
Here’s the demo sketch:
Click to expand
/* PDF export with file selector fail test
2020.08.16 raron
*/
import processing.pdf.*;
import static javax.swing.JOptionPane.*;
PGraphics originalG;
PGraphics pdf;
// PDF size
int pdfWidth = 2100;
int pdfHeight = 2970;
int pdfPages = 4; // nr. of test pages
File PDFfile = new File("New.pdf");
// Processing window size
int wWidth = 400;
int wHeight = 300;
// The buttons
verySimpleButton greenButton;
verySimpleButton redButton;
// Just some colors
color whiteCol = color( 200 );
color blackCol = color( 0 );
color bgCol = color( 24, 24, 24 );
color greenCol = color( 0, 80, 0 );
color redCol = color( 80, 0, 0 );
void settings()
{
size(wWidth, wHeight);
}
void setup()
{
originalG = g; // Save Processing default graphics renderer (afaik)
greenButton = new verySimpleButton( 66, 120, 100, 50, greenCol );
redButton = new verySimpleButton( 232, 120, 100, 50, redCol );
}
void draw()
{
background( bgCol );
fill( whiteCol );
textSize( 16 );
text("Press a button to attempt PDF export", 30, 75);
textSize( 12 );
text("Green button without file selector always works", 40, 210);
text("Red button with file selector sometimes mess up", 40, 240);
// Button updates
greenButton.display();
redButton.display();
}
void mouseClicked()
{
// This works regardless of dummy pdf or not
if (greenButton.underMouse()) exportToPDF("test.pdf");
// This sometimes fail
if (redButton.underMouse())
{
// Apparently, one has to make a dummy pdf before the file selection dialogue
// Or else it always fails (NullPointerException)
// It still fails sometimes, or makes a messed up pdf file mixed with the dummy pdf.
pdf = createGraphics(pdfWidth, pdfHeight, PDF, "dummy.pdf");
usePDF();
fill(greenCol); // might help to do something with the dummy pdf?
textSize( 80 );
text("DUMMY PDF", 100, 100);
g.dispose();
useOriginalG();
delay(200); // Seems to help?
selectOutput("Save file as", "exportToPDF", PDFfile);
}
}
void exportToPDF(File selection)
{
String PDFPathAndFile = selection.getAbsolutePath();
// Odd that this works to print without escaping the backslashes in the path strings (Windows)?
println("Absolute path : " + PDFPathAndFile);
showMessageDialog(null, "Will a PDF be exported?", "Not yet done...", INFORMATION_MESSAGE);
exportToPDF(PDFPathAndFile);
}
void exportToPDF(String filePath)
{
pdf = createGraphics(pdfWidth, pdfHeight, PDF, filePath);
// Start PDF export
usePDF();
fill( blackCol );
textSize( 50 );
// Some demo pages
for (int p=0; p<pdfPages; p++)
{
if( p>0 ) PDFnextPage();
text("TEST PAGE " + (p+1), pdfWidth/2, pdfHeight/2);
}
// End PDF export
g.dispose();
useOriginalG();
showMessageDialog(null, "PDF file exported!", "Done!", INFORMATION_MESSAGE);
}
// Draw to pdf
void usePDF()
{
g.endDraw();
g = pdf;
g.beginDraw();
}
// Start next PDF page
void PDFnextPage()
{
PGraphicsPDF pdfg = (PGraphicsPDF) pdf; // get the pdf renderer
pdfg.nextPage();
}
// Draw to processing window
void useOriginalG()
{
g.endDraw();
g = originalG;
g.beginDraw();
}
class verySimpleButton
{
int x,y,w,h;
color baseColor, hoverColor, pressColor, edgeColor;
verySimpleButton(int _bx, int _by, int _bw, int _bh, color _baseColor)
{
x = _bx;
y = _by;
w = _bw;
h = _bh;
baseColor = _baseColor;
hoverColor = lerpColor(baseColor, color(255, 255, 255), 0.2);
pressColor = lerpColor(baseColor, color(255, 255, 255), 0.4);
edgeColor = lerpColor(baseColor, color(255, 255, 255), 0.6);
}
void display()
{
fill(baseColor);
if (underMouse())
{
fill(hoverColor);
if(mousePressed) fill(pressColor);
}
stroke(edgeColor);
rect(x,y,w,h);
}
boolean underMouse()
{
if (mouseX>x && mouseX<x+w && mouseY>y && mouseY<y+h) return true;
return false;
}
}