Save pdf with "save as" dialog

edited July 2017 in Questions about Code

This might be a noob question but I'd like to save a pdf to a user specified folder. I could get both, saving pdfs (with the processing.pdf library) and getting a save as dialog (with selectOutput) to work but putting those two together gives me a nullPointerException.

For now, I'm just using my own "drawAndSave" method and don't even use the user specified location. If I put "drawAndSave()" inside the keyPressed() Method, it works, just not inside the selectOutput callback.

here is my code

import processing.pdf.*;

void setup(){
  size(300, 300);
}

void draw(){

}

void keyPressed(){
  if(key == 'q'){
    exit();
  }else if(key == 's'){
    selectOutput("Select desination;", "savePdf");
  }
}

public void drawAndSave(){
  beginRecord(PDF, "newFile.pdf");
  background(102);
  pushMatrix();
    // draw something
  popMatrix();
  endRecord();
}

void savePdf(File destination){
  if(destination != null){
    drawAndSave();
  }
}

Thank you very much

Answers

  • edited July 2017

    If you look at examples for selectOutput you'll see something like ... file.getAbsolutdPath (your destination)

    In savePdf copy this into a globat variable pathGlobal

    In line 20 use this pathGlobal instead of newFile.pdf without ""

  • Once you written desination

    Instead of destination?

    Or some other language involved here?

    It would be polite to write Hit q for quit and s for save graphic or so.

    Iirc selectOutput allows you to make only pdfs (and not other file types)

  • Thank you Chris for your answer :) If I use your method (saving the path into a global variable), the user would have to select the destination BEFORE even pressing save (or as I temporarily put it, with hitting "s"). I don't want that, though. I want a regular "save as" functionality, where the user hits save, then the dialog shows up and then after entering a path, drawAndSave() should be immediately called.

    desination was just a typo but that'd just the string for the title of the dialog, that shouldn't be the problem.

    The keyboard shortcuts are just temporarily, so no need to tell the user ;)

    There is no other language involved, just the above code.

    I also only want to make pdfs, I don't need anything else :)

  • edited July 2017

    No, my idea is correct.

    When you copy into the global var pathGlobal from destination between lines 29 and 30 it'll work as desired

  • Oh, I get what you mean now. I know that I'm not actually using the users filepath. Right now I expect that, regardless what the user specifies, a pdf file called "newFile.pdf" is created. I just want to use the callback from selectOutput right now, I am getting a nullPointerException though:

    java.lang.RuntimeException: Problem saving the PDF file.
        at processing.pdf.PGraphicsPDF.beginDraw(Unknown Source)
        at processing.core.PApplet.handleDraw(PApplet.java:2401)
        at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1547)
        at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:316)
    Caused by: java.lang.NullPointerException
        at com.lowagie.text.Document.open(Unknown Source)
        ... 4 more
    
  • Show your entire code as above (without graphics part) please

  • The above code is my entire Code. If you copy paste this in a sketch, run it, press s, hit save in the dialog, then you should get the same nullPointerException. If not, then something with my processing installation must be wrong.

  • Answer ✓

    Interesting

    Maybe you need to use my var and check it in draw whether if(!pathGlobal.equals("")).... and call drawAndSave from draw and not from savePdf ?

  • Otherwise I don't know

  • Answer ✓

    This works as @Chrisir suggested. You still need to use file.getAbsolutdPath().

    Kf

    import processing.pdf.*;
    
    boolean saveNow=false;
    
    void setup() {
      size(300, 300);
    }
    
    void draw() {
    
      if(saveNow){
        saveNow=false;
        drawAndSave();
      }
    }
    
    void keyPressed() {
      if (key == 'q') {
        exit();
      } else if (key == 's') {
        selectOutput("Select desination;", "savePdf");
      }
    }
    
    public void drawAndSave() {
      beginRecord(PDF, "newFile.pdf");
      background(102);
      pushMatrix();
      // draw something
      popMatrix();
      endRecord();
    }
    
    void savePdf(File destination) {
      if (destination != null) {
        saveNow=true;
      }
    }
    
  • Ok, it works, thank you!

    Still don't understand though, why I can't call drawAndSave() inside the callback directly...

    But thank you guys for your help, really appreciate it :)

  • Answer ✓

    All operations involving the sketch has to be done within the draw function, either inside the function or handled by other functions called from within draw. In your case, you are drawing from a callback function related to selectOutput(). This function is asynch and running in its own thread which has nothing to do with the main drawing thread.

    Kf

  • of course, that makes sense, thank you! :)

Sign In or Register to comment.