问题在于:
我目前必须打印一个包含当前javaFx场景“部分”的a4横向页面。
我必须打印的部件是BorderPane的一部分,我需要打印Left,Center和Bottom节点,这样打印的页面应如下所示:
打印最重要的是中心部分。它必须尽可能宽/高。基本上,左边部分可以占据页面宽度的最大10%,底部可以占页面高度的10-15%。因此,中心项目应拉伸至适合(可打印)页面宽度的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页面已拉伸... ^^
此处宽度/高度的输出与我之前获得的快照宽度/高度不同...
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:
使用快照的新尝试& 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();
}
}
我确实删除了这段代码的缩放部分,它实际上在打印时给出了以下输出:
更新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文件中。这很好,分辨率很好。所以问题出现在印刷部分......
答案 0 :(得分:2)
getPrintableWidth()和getPrintableHeight()在 1 / 72 英寸中返回其大小。 getWidth()和getHeight()以像素为单位返回大小。
要划分等效单位,您可以使用JobSettings的printResolution属性将像素转换为英寸:
double width = bpToPrint.getWidth();
double height = bpToPrint.getHeight();
// Convert to inches
PrintResolution resolution = job.getJobSettings().getPrintResolution();
width /= resolution.getFeedResolution();
height /= resolution.getCrossFeedResolution();
double scaleX = pageLayout.getPrintableWidth() / 72 / width;
double scaleY = pageLayout.getPrintableHeight() / 72 / height;
请注意,如果Node的getWidth()和getHeight()方法不在可见阶段,则它可能返回零,除非首先调用applyCss()
和layout()
方法,如{ {3}}:
作为一个更完整的示例,以下代码使用
applyCss()
和layout()
在显示舞台之前查找Button的宽度和高度。如果对applyCss()
的调用或对layout()
的调用已被注释掉,则对getWidth()
和getHeight()
的调用将返回零(直到显示舞台后的某个时间) 。
答案 1 :(得分:1)
这是解决方案,
经过多次研究后,问题似乎来自我用来打印的“临时”容器。即使调用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);
答案 2 :(得分:0)
点是距离(1/72英寸)的度量,而像素仍然是绝对值。 该API可以为您提供屏幕每英寸的像素(点)数量。将每英寸72点除以每英寸检索到的像素数量,可为您提供所需的因子:
double scaleX = 72.0/(Screen.getPrimary().getDpi());
double scaleY = scaleX;
如果将Scale实例添加到“ getTransforms()”(在问题中已完成),这就足够了。如果将比例尺应用为:
bp.setScaleX(scaleX);
还需要进行一次更正,因为该方法从中心缩放:
bp.setTranslateX(bp.getTranslateX() - bp.getBoundsInParent().getMinX());
(Y也是如此)