问题来了:
我目前必须打印一个 a4 横向页面,其中包含我当前 javaFx 场景的“部分”。
我要打印的部分是 BorderPane 的一部分,我需要打印 Left、Center 和 Bottom 节点,因此打印页面应该如下所示:
打印最重要的是中心部分。它必须尽可能宽/高。基本上,左侧部分最多可以占页面宽度的 10%,底部可以占页面高度的 10-15%。因此,中心项目应拉伸(stretch)以适应 90% 的(可打印)页面宽度和 85% 的(可打印)页面高度。
我实际上尝试了一些没有成功的解决方案......我确实创建了一个打印按钮,其行为如下:
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());
当我尝试这段代码时,打印机收到一个作业,“打印”一页……空白页!上面什么都没有印...
如果我删除“缩放”部分,我会在页面上打印一些内容,但它根本不考虑页面大小...
我也确实尝试过“快照”节点,所以我可以检查它们的属性(宽度、高度),但没有找到任何方法来“连接它们”并打印结果...
// 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());
我将其作为输出(仅供引用):
left item width : 112.0 height : 892.0
center item width : 1746.0 height : 892.0
bottom item width : 1858.0 height : 95.0
感谢您的帮助/阅读,非常感谢任何帮助。
更新 01:
这是“更新后的代码”:
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);
打印结果只显示在我的 vToPrint 框的左上角,延伸到整个 a4 页面...^^
而且这里输出的width/height和我之前得到的snapshot width/height不一样...
left item width : 112.0 height : 892.0
center item width : 1746.0 height : 892.0
bottom item width : 1858.0 height : 95.0
这真是令人困惑......
更新 02:
快照和 ImageView 的新尝试:
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();
}
}
我确实删除了这段代码的比例部分,它实际上给了我以下打印输出:
更新 03:
现在我得出了一个结果,但是打印解析好像失败了。而不是/72 比例(如更新 01 中那样):
double scaleX = pageLayout.getPrintableWidth() / 72 / width;
我确实将它除以 600(就像 resolution.getFeedResolution)...但这可能是错误的,因为我之前已经将它除以 600...:
width /= resolution.getFeedResolution();
// ...
double scaleX = pageLayout.getPrintableWidth() / width / 600;
结果在 a4 横向页面上打印了“vToPrint”vbox,但是分辨率真的、真的、真的……很糟糕!整件事都是像素化的。文本可读,但现在打印分辨率有问题...
我还尝试制作要打印的节点的快照,因此我构建了 vToPrint VBox,然后对其进行快照,并将快照保存到 .png 文件中。这很好,分辨率很好。所以现在问题出在打印部分......
最佳答案
这是解决方案,
经过多次研究,问题似乎出在我用来打印的“临时”容器上。即使调用了 applyCss()、layout() 或 autosize(),它也不会真正渲染容器。
我找到的实际解决方案是使用“真正的”容器,并在启动 printJob 之前隐藏我不想打印的项目。
这是我目前使用的代码:
PrinterJob job = PrinterJob.createPrinterJob();
if(job != null && job.showPrintDialog(root.getScene().getWindow())){
Printer printer = job.getPrinter();
PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.LANDSCAPE, Printer.MarginType.HARDWARE_MINIMUM);
root.getTop().setVisible(false);
root.getTop().setManaged(false);
double width = root.getWidth();
double height = root.getHeight();
PrintResolution resolution = job.getJobSettings().getPrintResolution();
width /= resolution.getFeedResolution();
height /= resolution.getCrossFeedResolution();
double scaleX = pageLayout.getPrintableWidth()/width/600;
double scaleY = pageLayout.getPrintableHeight()/height/600;
Scale scale = new Scale(scaleX, scaleY);
root.getTransforms().add(scale);
boolean success = job.printPage(pageLayout, root);
if(success){
job.endJob();
}
root.getTransforms().remove(scale);
}
root.getTop().setManaged(true);
root.getTop().setVisible(true);
关于java - 使用 JavaFX 打印节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44678747/