I have a javafx TabPane that I want to be able to print. The TabPane has two tabs, and I want each tab to be printed on its own page. I created a button on one of the tabs with the onAction function to run a method called onPrint. The button will print a table within one tab and another table in the other.
The printer.fxml file
<ScrollPane fx:id="assessment"/>
<Pane fx:id="printPane">
<TabPane prefHeight="900.0" prefWidth="937.0" tabClosingPolicy="UNAVAILABLE">
<Tab text="Issues">
<AnchorPane fx:id="issuesTab" minHeight="0.0" minWidth="0.0" prefHeight="519.0" prefWidth="585.0">
<Text text="here is some text" />
<Button fx:id="print" layoutX="82.0" layoutY="60.0" mnemonicParsing="false" onAction="#onPrint" text="print" />
</AnchorPane>
</Tab>
<Tab text="Function">
<AnchorPane fx:id="FunctionTab" prefHeight="400.0" prefWidth="600.0">
<Text text="here is some text"/>
</AnchorPane>
</Tab>
</Pane>
</Scrollpane>
I've tried several different ways to get this to work properly. I'll walk through them below.
The printerController file is as follows:
public ScrollPane assessment;
public Pane printerPane;
public AnchorPane issuesTab;
public AnchorPane functionTab;
public void onPrint(ActionEvent event) {
printPane.getChildren().addAll(issuesTab, functionTab);
Printer printer = Printer.getDefaultPrinter();
PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
PrinterJob job = PrinterJob.createPrinterJob();
job.getJobSettings().setPageRanges(new PageRange(1, 2));
if (job.showPrintDialog(printPane.getScene().getWindow())){
boolean success = job.printPage(pageLayout, printPane);
if (success) {
job.endJob();
}
}
}
Currently this works but it adds both tables ontop of each other. I've tried to use the setPageRanges function to set a page range but I cannot get it to work propertly.
I then thought maybe I need to create a brand new pane for each tab and then add those to a group and it'll print separately.
private Node toPrint;
private Node printAllPages(){
if(toPrint== null){
Group group = new Group();
group.getChildren().addAll(
new Pane(issuesTab),
new Pane(functionTab)
);
notToPrint = group;
}
return notToPrint;
}
public void onPrint(ActionEvent event) {
PrinterJob job = PrinterJob.createPrinterJob();
if(job.showPrintDialog(notToPrint.getScene().getWindow())){
boolean success = job.printPage(printAllPages());
if(success){
job.endJob();
}
}
}
However this results in the following error - Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.Node.getScene()" because "this.notToPrint" is null. I also don't believe this is the right approach.
Are there any Printer, PageLayout or PrinterJob settings that I need to apply so that each AnchorPane can be printed on separate pages?
Edits made:
Per @SedJ601 advice on how to fix this issue. I went through the link he provided and decided to try this -
PrintController.java
public TabPane allTabs;
Printer printer = Printer.getDefaultPrinter();
PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.DEFAULT);
PrinterJob job = PrinterJob.createPrinterJob();
if(job.showPrintDialog(allTabs.getScene().getWindow())){
double pagePrintableHeight = pageLayout.getPrintableHeight();
double pagePrintableWidth = pageLayout.getPrintableWidth();
double scaleX = pagePrintableWidth / allTabs.getBoundsInParent().getWidth();
double localScale = scaleX;
double numberOfPages = Math.ceil((allTabs.getPrefWidth()) * localScale) / pagePrintableHeight;
System.out.println(numberOfPages);
for(int i = 0; i < numberOfPages; i++){ job.printPage(pageLayout, allTabs.get(i)); } job.endJob();
}else{
System.out.println("This did not work");
}
Print.fxml
<ScrollPane fx:id="assessment">
<TabPane fx:id="allTabs" prefHeight="900.0" prefWidth="937.0" tabClosingPolicy="UNAVAILABLE">
<Tab text="Issues">
<content>
<AnchorPane fx:id="issuesTab" minHeight="0.0" minWidth="0.0" prefHeight="519.0" prefWidth="585.0">
<Text text="some text" />
</AnchorPane>
</content>
</Tab>
<Tab text="Function">
<content>
<AnchorPane fx:id="functionTab" prefHeight="400.0" prefWidth="600.0">
<Text text="some text" />
</AnchorPane>
</content>
</Tab>
</TabPane>
However this is printing only the first tab. I tried setting the numberOfPages value equal to 10.0 and still only the first tab prints. How do I edit either the for loop to loop through both tabs or change the numberOfPages to accurately find all pages?
printerPane
vsprintPane
.AnchorPanes
on two different pages, print theAnchorPanes
individually and not thePrint(er)Pane
for(int i = 0; i < numberOfPages; i++) { job.printPage(pageLayout, tblvMain); }
Where you loop through theAnchorPanes
.