6

In my javafx application , I'm using JavaFX 8 printing API to print a node , i am getting problem of the printing area , despite i have set the pageLayout with A4 paper .... here is my code :

public static  void printNode(final Node node) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Printer printer = Printer.getDefaultPrinter();   
        PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, 0,0,0,0 );      
        PrinterJob job = PrinterJob.createPrinterJob();
        if (job != null  && job.showPrintDialog(node.getScene().getWindow()) ) { 
            boolean success = job.printPage(pageLayout, node);                   
            if (success) {
                job.endJob();
            }
        }

And here is a snapshot of the node that i want to print it is : enter image description here

and here is what i am getting when i print the node enter image description here

KacemSys
  • 111
  • 3
  • 13

2 Answers2

8

In your method you need to get the hardware able margins. Even if you set the margins to 0, your printer has a non printable margin around the sheet.

You can view the margins if you print them out:

System.out.println("PageLayout: " + pageLayout.toString());

And you are not able to set the margins to a value less than zero. So you need to scale your Node that would be printed. The node will be scaled, printed and then unscaled.

  public static void printNode(final Node node) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
    Printer printer = Printer.getDefaultPrinter();
    PageLayout pageLayout
        = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
    PrinterAttributes attr = printer.getPrinterAttributes();
    PrinterJob job = PrinterJob.createPrinterJob();
    double scaleX
        = pageLayout.getPrintableWidth() / node.getBoundsInParent().getWidth();
    double scaleY
        = pageLayout.getPrintableHeight() / node.getBoundsInParent().getHeight();
    Scale scale = new Scale(scaleX, scaleY);
    node.getTransforms().add(scale);

    if (job != null && job.showPrintDialog(node.getScene().getWindow())) {
      boolean success = job.printPage(pageLayout, node);
      if (success) {
        job.endJob();

      }
    }
    node.getTransforms().remove(scale);
  }

Inspired by the solution found here: https://carlfx.wordpress.com/2013/07/15/introduction-by-example-javafx-8-printing/

aw-think
  • 4,723
  • 2
  • 21
  • 42
  • The margins have to be >=0 , here is the exception : `Caused by: java.lang.IllegalArgumentException: Margins must be >= 0 at javafx.print.Printer.createPageLayout(Printer.java:346) at classes.JavaFxPrint.printNode(JavaFxPrint.java:31)` – KacemSys Jul 05 '15 at 16:01
  • @KradraBelkacem I've updated my answer, so now it should fit your question. – aw-think Jul 05 '15 at 16:12
  • i'm getting the same problem, the print method is not covering all node. what about the objet PrinterAttributes ? why haven't you used it . – KacemSys Jul 05 '15 at 16:16
  • PrinterAttributes is read only, it reflects the ability of you device. If scale not enough, scale more down, until it fits to the page. – aw-think Jul 05 '15 at 17:01
  • @NwDx : Can you please check this question about printing with JavaFX : http://stackoverflow.com/questions/34815660/javafx-image-getting-scaled-to-25-and-then-getting-printed – We are Borg Jan 15 '16 at 16:38
0

EDIT (after Menai Ala Eddine remark): If you want to print a Region (child of Node and parent of all controls and panes and charts), then you can change the parameter Node with Region and use this solution: [END_EDIT]

Since I cannot add any comments, I will place my solution here. I modified @NwDx's answer (it didn't work for me, I ended up with some weird scaling) by setting prefSize of the node to the printing page layout size, with this line of code:

node.setPrefSize(pageLayout.getPrintableWidth(), pageLayout.getPrintableHeight());

The whole snippet now looks something like this:

public static void printNode(final Region region) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
    Printer printer = Printer.getDefaultPrinter();
    PageLayout pageLayout
        = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
    PrinterJob job = PrinterJob.createPrinterJob();

     region.setPrefSize(pageLayout.getPrintableWidth(), pageLayout.getPrintableHeight());
    if (job != null && job.showPrintDialog(region.getScene().getWindow())) {
      boolean success = job.printPage(pageLayout, region);
      if (success) {
        job.endJob();
      }
    }
  }
  • I can't find _setPrefSize_ symbol for node. – Menai Ala Eddine - Aladdin Sep 01 '17 at 15:02
  • Oh it's my mistake. I used AnchorPane for this example and didn't check that here the param is of type Node, which is an abstract class and doesn't include this method. What I'd do is, if you plan on using it with the same parameter, cast it accordingly and then use this method. Although this will work only for Region type nodes, I'll edit my answer :) Thanks – smashbotica Sep 02 '17 at 18:06
  • Just adding -instanceof_ to specify type of your nodes. – Menai Ala Eddine - Aladdin Sep 02 '17 at 18:10