Here is the problem :
I currently have to print a a4, landscape page containing "parts" of my current javaFx scene.
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 :
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.
I actually tried few solutions without success... I did create a print button that acts like this :
PrinterJob job = PrinterJob.createPrinterJob();
BorderPane bpToPrint = new BorderPane();
bpToPrint.setLeft(sourceBorderPane.getLeft());
bpToPrint.setCenter(sourceBorderPane.getCenter());
bpToPrint.setBottom(sourceBorderPane.getBottom());
if(job != null && 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());
When I try this piece of code, the printer receives a job, "prints" a page... A blank page! Nothing printed on it...
If I remove the "scale" part, I have something that prints on the page, but it does NOT respect the page size at all...
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...
// 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());
I get this as output (just for information) :
left item width : 112.0 height : 892.0
center item width : 1746.0 height : 892.0
bottom item width : 1858.0 height : 95.0
Thanks for help/reading, any help really appreciated.
Update 01 :
Here is the "updated 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 & 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 && 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);
The print result shows just the top left corner of my vToPrint box, stretched over a whole a4 page...^^
And the output of width / height here are not the same as the snapshot width/height I got earlier...
left item width : 112.0 height : 892.0
center item width : 1746.0 height : 892.0
bottom item width : 1858.0 height : 95.0
This is really confusing...
Update 02 :
New try with snapshots & imageViews :
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 && 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();
}
}
I did remove the scale part of this piece of code and it actually gives me the following output on printing :
Update 03 :
Now I come to a result, but print resolution seems to fail. Instead of /72 the scale (as in Update 01) :
double scaleX = pageLayout.getPrintableWidth() / 72 / width;
I did divide it with 600 (like the resolution.getFeedResolution)... But it's probably wrong since I already divided it with 600 earlier... :
width /= resolution.getFeedResolution();
// ...
double scaleX = pageLayout.getPrintableWidth() / width / 600;
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...
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...