title: Printing Nodes with JavaFX
body: <p>Here is the problem : </p>
  
  <p>I currently have to print a a4, landscape page containing "parts" of my current javaFx scene.</p>
  
  <p>The parts I have to print are parts of a BorderPane, I need to print the Left, Center and Bottom nodes so the printed page should look like this : </p>
  
  <p><a href="https://i.stack.imgur.com/ND08g.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ND08g.jpg" alt="Second A4 Template Image"></a></p>
  
  <p>The most important thing to print is the Center part. It must be as wide/tall as possible. Basically, the Left part can take like max 10% of the page width, and the bottom could take like 10-15% of the page height. So, the center item should stretch to fit 90% of (printable) page width and 85% of (printable) page height.</p>
  
  <p>I actually tried few solutions without success... I did create a print button that acts like this : </p>
  
  <pre><code>PrinterJob job = PrinterJob.createPrinterJob();
  
  BorderPane bpToPrint = new BorderPane();
  bpToPrint.setLeft(sourceBorderPane.getLeft());
  bpToPrint.setCenter(sourceBorderPane.getCenter());
  bpToPrint.setBottom(sourceBorderPane.getBottom());
  
  if(job != null &amp;&amp; job.showPrintDialog(root.getScene().getWindow())){
      Printer printer = job.getPrinter();
      PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.LANDSCAPE, Printer.MarginType.HARDWARE_MINIMUM);
  
      double scaleX = pageLayout.getPrintableWidth() / bpToPrint.getWidth();
      double scaleY = pageLayout.getPrintableHeight() / bpToPrint.getHeight();
  
      Scale scale = new Scale(scaleX, scaleY);
  
      bpToPrint.getTransforms().add(scale);
  
      boolean success = job.printPage(pageLayout, bpToPrint);
      if(success){
          job.endJob();
      }
  }
  
  // Since I did "move" the nodes to the "bpToPrint" borderpane
  // I have to put them back to the "source"
  
  sourceBorderPane.setBottom(bpToPrint.getBottom());
  sourceBorderPane.setLeft(bpToPrint.getLeft());
  sourceBorderPane.setCenter(bpToPrint.getCenter());
  </code></pre>
  
  <p><strong>When I try this piece of code, the printer receives a job, "prints" a page... A blank page! Nothing printed on it...</strong></p>
  
  <p>If I remove the "scale" part, I have something that prints on the page, but it does NOT respect the page size at all...</p>
  
  <p>I also did try to "snapshot" the nodes, so I can check their attributes (width, height), but did not find any way to "concat them" and print the result...</p>
  
  <pre><code>// WritableImage myLeft = bPane.getLeft().snapshot(null,null);
  // System.out.println("left item width : "+myLeft.getWidth()+" height : "+myLeft.getHeight());
  // WritableImage myCenter = bPane.getCenter().snapshot(null,null);
  // System.out.println("center item width : "+myCenter.getWidth()+" height : "+myCenter.getHeight());
  // WritableImage myBottom = bPane.getBottom().snapshot(null,null);
  // System.out.println("Bottom item width : "+myBottom.getWidth()+" height : "+myBottom.getHeight());
  </code></pre>
  
  <p>I get this as output (just for information) : </p>
  
  <pre><code>left item width : 112.0 height : 892.0
  center item width : 1746.0 height : 892.0
  bottom item width : 1858.0 height : 95.0
  </code></pre>
  
  <p>Thanks for help/reading, any help really appreciated.</p>
  
  <p><strong>Update 01 :</strong></p>
  
  <p>Here is the "updated code" : </p>
  
  <pre><code>PrinterJob job = PrinterJob.createPrinterJob();
  Node myLeft = root.getLeft();
  Node myCenter = root.getCenter();
  Node myBottom = root.getBottom();
  
  //I will use a HBox to put the left &amp; center, and a VBox to put hbox + bottom
  VBox vToPrint = new VBox();
  HBox hToPrint = new HBox();
  
  hToPrint.getChildren().addAll(myLeft, myCenter);
  vToPrint.getChildren().addAll(hToPrint,myBottom);
  
  //Next lines come from the applyCss example               
  Group tempRoot = new Group();
  Scene tempScene = new Scene(tempRoot);
  tempRoot.getChildren().add(vToPrint);
  
  tempRoot.applyCss();
  tempRoot.layout();            
  
  if(job != null &amp;&amp; job.showPrintDialog(root.getScene().getWindow())){
      Printer printer = job.getPrinter();
      PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.LANDSCAPE, Printer.MarginType.HARDWARE_MINIMUM);
  
      double width = vToPrint.getWidth();
      System.out.println("WIDTH : "+width);
      //Output : 852.0
  
      double height = vToPrint.getHeight();
      System.out.println("HEIGHT : "+height);
      //Output : 803.0
  
      PrintResolution resolution = job.getJobSettings().getPrintResolution();
  
      System.out.println("FEEDRESOLUTION : "+resolution.getFeedResolution());
      //Output : 600
  
      System.out.println("CROSSFEEDRESOLUTION : "+resolution.getCrossFeedResolution());
      //Output : 600
  
  
      width /= resolution.getFeedResolution();
      System.out.println("NEW WIDTH : "+width);
      //Output : 1.42
  
      height /= resolution.getCrossFeedResolution();
      System.out.println("NEW HEIGHT : "+height);
      //Output : 1.3383333333333334
  
      double scaleX = pageLayout.getPrintableWidth() / 72 / width;
      System.out.println("SCALE X : "+scaleX);
      //Output : 8.01056338028169
  
      double scaleY = pageLayout.getPrintableHeight() / 72 / height;
      System.out.println("SCALE Y : "+scaleY);
      //Output : 5.935252677755962
  
      Scale scale = new Scale(scaleX, scaleY);
  
      vToPrint.getTransforms().add(scale);
  
      boolean success = job.printPage(pageLayout, vToPrint);
  
      if(success){
          job.endJob();
      }
  }
  root.setLeft(myLeft);
  root.setCenter(myCenter);
  root.setBottom(myBottom);
  </code></pre>
  
  <p>The print result shows just the top left corner of my vToPrint box, stretched over a whole a4 page...^^</p>
  
  <p>And the output of width / height here are not the same as the snapshot width/height I got earlier... </p>
  
  <pre><code>left item width : 112.0 height : 892.0
  center item width : 1746.0 height : 892.0
  bottom item width : 1858.0 height : 95.0
  </code></pre>
  
  <p>This is really confusing... </p>
  
  <p><strong>Update 02 :</strong></p>
  
  <p>New try with snapshots &amp; imageViews : </p>
  
  <pre><code>PrinterJob job = PrinterJob.createPrinterJob();
  WritableImage myLeftImg = root.getLeft().snapshot(null, null);
  WritableImage myCenterImg = root.getCenter().snapshot(null, null);
  WritableImage myBottomImg = root.getBottom().snapshot(null, null);
  
  ImageView myLeftImgView = new ImageView();
  ImageView myCenterImgView = new ImageView();
  ImageView myBottomImgView = new ImageView();
  
  myLeftImgView.setImage(myLeftImg);
  myCenterImgView.setImage(myCenterImg);
  myBottomImgView.setImage(myBottomImg);
  
  VBox vToPrint = new VBox();
  HBox hToPrint = new HBox();
  hToPrint.getChildren().addAll(myLeftImgView, myCenterImgView);
  vToPrint.getChildren().addAll(hToPrint, myBottomImgView);
  
  Group myRoot = new Group();
  Scene myScene = new Scene(myRoot);
  myRoot.getChildren().add(vToPrint);                
  
  myRoot.applyCss();
  myRoot.layout();
  
  if(job != null &amp;&amp; job.showPrintDialog(root.getScene().getWindow())){
      Printer printer = job.getPrinter();
      PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.LANDSCAPE, Printer.MarginType.HARDWARE_MINIMUM);
      boolean success = job.printPage(pageLayout, vToPrint);
      if(success){
          job.endJob();
      }
  }
  </code></pre>
  
  <p>I did remove the scale part of this piece of code and it actually gives me the following output on printing : </p>
  
  <p><a href="https://i.stack.imgur.com/hp5nl.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/hp5nl.jpg" alt="enter image description here"></a></p>
  
  <p><strong>Update 03 :</strong></p>
  
  <p>Now I come to a result, but print resolution seems to fail. Instead of /72 the scale (as in Update 01) :</p>
  
  <pre><code>double scaleX = pageLayout.getPrintableWidth() / 72 / width;
  </code></pre>
  
  <p>I did divide it with 600 (like the resolution.getFeedResolution)... But it's probably wrong since I already divided it with 600 earlier... : </p>
  
  <pre><code>width /= resolution.getFeedResolution();
  // ... 
  double scaleX = pageLayout.getPrintableWidth() / width / 600;
  </code></pre>
  
  <p>The result prints the "vToPrint" vbox on a a4 landscape page, BUT resolution is really, really, really, ... Bad! The whole thing is pixelized. Texts are readable but there is something wrong now with the print resolution...</p>
  
  <p>I also tried to make a snapshot of the nodes to print, so I build my vToPrint VBox, then snapshot it, and save the snapshot into a .png file. This is good, the resolution is fine. So the problem is in the print part now...</p>