当前位置: 首页 > 知识库问答 >
问题:

使用JavaFX打印节点

安聪
2023-03-14

问题就在这里:

我目前必须打印一个a4的横向页面,其中包含当前javaFx场景的“部分”。

我必须打印的部分是BorderPane的部分,我需要打印左侧、中间和底部节点,所以打印的页面应该如下所示:

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);
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();
    }
}

double scaleX = pageLayout.getPrintableWidth() / 72 / width;

我把它除以600(就像Resolution.GetFeedResolution)...但这可能是错误的,因为我之前已经把它和600分了...:

width /= resolution.getFeedResolution();
// ... 
double scaleX = pageLayout.getPrintableWidth() / width / 600;

结果将“Vtoprint”vbox打印在a4景观页面上,但分辨率真的,真的,真的,……糟糕!整件事都像素化了。文本是可读的,但现在打印分辨率出了问题。

我还尝试制作要打印的节点的快照,因此我构建了vToPrint VBox,然后对其进行快照,并将快照保存到.png文件中。这很好,分辨率很好。所以现在问题出在打印部分...

共有1个答案

鲜于煜祺
2023-03-14

点是距离的度量(1/72英寸),而像素仍然是绝对值。该API可以为您的屏幕获取每英寸的像素(点)量。将每英寸72个点除以检索到的每英寸像素量,就会得到所需的系数:

double scaleX = 72.0/(Screen.getPrimary().getDpi());
double scaleY = scaleX;

如果添加一个Scale-instance来“get transforms()”(如问题中所做),这就足够了。如果您将该刻度应用为:

bp.setScaleX(scaleX);

还需要进行一次修正,因为该方法从中心缩放:

bp.setTranslateX(bp.getTranslateX() - bp.getBoundsInParent().getMinX());
 类似资料:
  • 问题内容: 我正在使用Angular JS和Node JS开发应用程序,我需要查看用户机器中所有可用的打印机,让用户选择其中一台并打印收据。 有没有办法做到这一点? 问题答案: 我做了一个这样的应用程序。我使用http://nwjs.io/和注释中的模块来完成它:https : //www.npmjs.com/package/printer,这是该模块打印的有效代码在默认打印机中原始文件: 您可以

  • 我创建了一个小节点应用程序,从GitHub jobs API获取作业。我正在使用模块来完成此操作。您可以看到下面的代码: 如果您能帮助打印JSON对象,我将不胜感激,目前它只打印。

  • 我有一个连接到CUPS的打印机,它支持双面打印,如何通过java例程将其设置为单面打印或双面打印? 我曾尝试使用它的库使用ASET添加和addViewer首选项没有任何运气。 有人能提供一些建议吗?

  • 我目前的工作是创建机械图纸,用于发送给客户和作为施工图。当我的绘图完成后,我导出一个. pdf文件,并将其发送给客户端。 我们的客户非常喜欢黑白画,所以我试着提供他们。但是我用来画画的软件效果不好。它只有一个选项“所有颜色都是黑色”,我的画上有一些白色的“隐藏线”。当然,这些显示使用所有颜色作为黑色选项。 我找到了一个解决方案,那就是使用pdf打印机。效果很好,效果也很好。 现在我想打印这个。pd

  • 为了处理文字和图形而使用视讯显示器时,设备无关的概念看来非常完美,但对于打印机,设备无关的概念又怎样呢? 总的说来,效果也很好。在Windows程序中,用于视讯显示器的GDI函数一样可以在印表纸上打印文字和图形,在以前讨论的与设备无关的许多问题(多数都与平面显示的尺寸、分辨率以及颜色数有关)都可以用相同的方法解决。当然,一台打印机不像使用阴极射线管的显示器那么简单,它们使用的是印表纸。它们之间有一

  • 我需要发送一个pdf文件打印在一个网络应用程序的服务器端,打印机完全支持pdf打印等,它是网络以及服务器。pdf也存储在服务器上。 我尝试的是点击一个按钮,打印出pdf文件,目前我有以下代码: 但我有几个问题,我如何将pdf放入输入流以打印出来,我可以选择诸如双面打印之类的选项,以及如何从JSF web应用程序中调用它 谢谢