2

I am attempting to send some potentially long text to a printer for... well, printing. Here is a minimal example that demonstrates how I am currently printing text:

@FXML
private void print() {
    Text printText = new Text(textArea.getText());
    TextFlow printArea = new TextFlow(printText);
    printArea.setTextAlignment(TextAlignment.LEFT);
    printArea.setMaxHeight(Region.USE_COMPUTED_SIZE);

    PrinterJob printerJob = PrinterJob.createPrinterJob();

    if (printerJob != null && printerJob.showPrintDialog(textArea.getScene().getWindow())) {

        PageLayout pageLayout = printerJob.getJobSettings().getPageLayout();
        printArea.setMaxWidth(pageLayout.getPrintableWidth());

        if (printerJob.printPage(pageLayout, printArea)) {
            printerJob.endJob();
            // done printing
        } else {
            System.err.println("Printing failed!");
        }

    } else {
        System.err.println("Unable to create printer job or printer dialog cancelled by user");
    }
}

The code above prints text as expected, except that no matter how much text is being printed, it always prints just a single page. In the print dialog that is shown, under the section for "Print range", I have been selecting the "All" option. I have tried choosing the "Pages" option (which for some reason has been defaulting from 1 to 9999 - this is a little odd since the text should be at most two pages long), but have not had any success in printing more than a single page. I have also tried manually setting the page range on the JobSettings object, but that didn't seem to do anything either.

enter image description here

How can I use the PrinterJob and its related classes to get a long piece of text to properly print on multiple pages?

Cypher
  • 2,608
  • 5
  • 27
  • 41

1 Answers1

1

As far as I know you need to supply multiple Nodes, printAreas in your case, to the PrinterJob, having divided them up beforehand in your code (unfortunately...) Placing your TextFlow in a styled Scene will give you the total size, you can divide that up based on the PageLayout.getPrintableWidth and getPrintableHeight, with the proviso that the user can potentially alter these in the print settings dialog.

job.getJobSettings().setPageRanges(new PageRange(1, numPages));

Tells the job how many pages you can supply. You generally set this before showing the print dialog so that the user can choose how many pages to print, what range etc.

After showing the dialog the JobSettings will be updated with the selected PageRanges the user has chosen, which you then loop over and print individually.

if (job.showPrintDialog(null)) {
    JobSettings js = job.getJobSettings();
    for (PageRange pr : js.getPageRanges()) {
        for (int p = pr.getStartPage(); p <= pr.getEndPage(); p++) {
            boolean ok = job.printPage(...code to get your node for the page...);
            ...take action on success/failure etc.
        }
    }
}
Geoff
  • 568
  • 4
  • 11
  • 2
    Instead of printing multiple nodes, I just ended up calculating the height of the printable area in pixels, and using the `setTranslateY()` method on the parent node to "shift the page up" that amount before calling `printPage()` again on the same node. Not sure if that's the "correct" way to do things, but I found it to work out the best for my case. Thanks for the tip! – Cypher Nov 23 '16 at 19:16
  • An interesting approach that has me thinking... it might be a better way of dealing with tables than my current approach. Thanks! – Geoff Nov 29 '16 at 01:51
  • @Cypher thanks! do you think you could provide a full code example? – cashmash Jan 22 '18 at 19:45
  • how to get the paper source for each page ? – Arpan Aug 07 '18 at 10:59
  • @Arpan the JobSettings object contains the paper source and page layout selected by the user in the print dialog. [JobSettings API](https://docs.oracle.com/javase/8/javafx/api/javafx/print/JobSettings.html) – Geoff Aug 08 '18 at 23:08