JavaFX8打印API:如何正确设置可打印区域

6

在我的JavaFX应用程序中,我正在使用JavaFX 8打印API来打印一个节点,尽管我已经设置了A4纸张的页面布局,但是我仍然遇到了打印区域的问题...以下是我的代码:

public static  void printNode(final Node node) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Printer printer = Printer.getDefaultPrinter();   
        PageLayout pageLayout = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, 0,0,0,0 );      
        PrinterJob job = PrinterJob.createPrinterJob();
        if (job != null  && job.showPrintDialog(node.getScene().getWindow()) ) { 
            boolean success = job.printPage(pageLayout, node);                   
            if (success) {
                job.endJob();
            }
        }

以下是我想打印的节点快照: 输入图像描述

以下是我打印节点时得到的内容: 输入图像描述

2个回答

8

在你的方法中,你需要获取硬件可用边距。即使你将边距设置为0,你的打印机也会在纸张周围留下不可打印的边距。

如果你想查看边距,可以将它们打印出来:

System.out.println("PageLayout: " + pageLayout.toString());

您不能将边距设置为小于零的值。因此,您需要缩放要打印的节点。该节点将被缩放、打印,然后再取消缩放。

  public static void printNode(final Node node) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
    Printer printer = Printer.getDefaultPrinter();
    PageLayout pageLayout
        = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
    PrinterAttributes attr = printer.getPrinterAttributes();
    PrinterJob job = PrinterJob.createPrinterJob();
    double scaleX
        = pageLayout.getPrintableWidth() / node.getBoundsInParent().getWidth();
    double scaleY
        = pageLayout.getPrintableHeight() / node.getBoundsInParent().getHeight();
    Scale scale = new Scale(scaleX, scaleY);
    node.getTransforms().add(scale);

    if (job != null && job.showPrintDialog(node.getScene().getWindow())) {
      boolean success = job.printPage(pageLayout, node);
      if (success) {
        job.endJob();

      }
    }
    node.getTransforms().remove(scale);
  }

灵感来自这里找到的解决方案:https://carlfx.wordpress.com/2013/07/15/introduction-by-example-javafx-8-printing/

该解决方案是关于JavaFX 8打印的介绍和示例。

边距必须大于等于0,以下是异常信息: Caused by: java.lang.IllegalArgumentException: Margins must be >= 0 at javafx.print.Printer.createPageLayout(Printer.java:346) at classes.JavaFxPrint.printNode(JavaFxPrint.java:31) - KacemSys
@KradraBelkacem 我已经更新了我的答案,现在它应该符合你的问题了。 - aw-think
我遇到了同样的问题,print方法没有覆盖所有节点。那么PrinterAttributes对象怎么样?为什么你没有使用它呢? - KacemSys
PrinterAttributes是只读的,它反映了您设备的能力。如果比例不够,请再缩小一些,直到适合页面。 - aw-think
@NwDx:您能否请您检查关于使用 JavaFX 打印的问题:http://stackoverflow.com/questions/34815660/javafx-image-getting-scaled-to-25-and-then-getting-printed - We are Borg

0

编辑Menai Ala Eddine 的评论后):如果您想要打印一个区域(Node的子级,所有控件、窗格和图表的父级),那么您可以将参数Node更改为Region并使用以下解决方案:[END_EDIT]

由于我无法添加任何评论,因此我将我的解决方案放在这里。我修改了@NwDx的答案(它对我没有用,我最终得到了一些奇怪的缩放),通过将节点的prefSize设置为打印页面布局大小,使用以下代码行:

node.setPrefSize(pageLayout.getPrintableWidth(), pageLayout.getPrintableHeight());

整个代码片段现在看起来像这样:
public static void printNode(final Region region) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
    Printer printer = Printer.getDefaultPrinter();
    PageLayout pageLayout
        = printer.createPageLayout(Paper.A4, PageOrientation.PORTRAIT, Printer.MarginType.HARDWARE_MINIMUM);
    PrinterJob job = PrinterJob.createPrinterJob();

     region.setPrefSize(pageLayout.getPrintableWidth(), pageLayout.getPrintableHeight());
    if (job != null && job.showPrintDialog(region.getScene().getWindow())) {
      boolean success = job.printPage(pageLayout, region);
      if (success) {
        job.endJob();
      }
    }
  }

我找不到节点的_setPrefSize_符号。 - Menai Ala Eddine - Aladdin
哦,这是我的错误。我在这个例子中使用了AnchorPane,并没有检查这里的参数是Node类型,它是一个抽象类,不包括这个方法。如果您计划使用相同的参数,我会进行强制转换,然后使用这个方法。虽然这只适用于区域类型节点,但我会编辑我的答案 :) 谢谢 - smashbotica
只需添加-instanceof_以指定节点类型。 - Menai Ala Eddine - Aladdin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接