# 基本印刷计划

> 原文： [https://docs.oracle.com/javase/tutorial/2d/printing/printable.html](https://docs.oracle.com/javase/tutorial/2d/printing/printable.html)

本节介绍如何创建显示打印对话框的基本打印程序，并将文本“Hello World”打印到所选打印机。

打印任务通常由两部分组成：

*   作业控制 - 创建打印作业，将其与打印机关联，指定份数和用户打印对话框交互。
*   页面映像 - 将内容绘制到页面，以及管理跨页面的内容（分页）。

首先创建打印机作业。表示打印机作业和大多数其他相关类的类位于 [`java.awt.print`](https://docs.oracle.com/javase/8/docs/api/java/awt/print/package-summary.html) 包中。

```
import java.awt.print.*;

PrinterJob job = PrinterJob.getPrinterJob();

```

接下来提供通过实现 [`Printable`](https://docs.oracle.com/javase/8/docs/api/java/awt/print/Printable.html) 接口将内容呈现给页面的代码。

```
class HelloWorldPrinter
              implements Printable { ... }
...
job.setPrintable(new HelloWorldPrinter());

```

应用程序通常显示打印对话框，以便用户可以调整各种选项，例如份数，页面方向或目标打印机。

```
boolean doPrint = job.printDialog();

```

在用户批准或取消打印之前，将显示此对话框。如果用户发出命令继续打印，则`doPrint`变量将为 true。如果`doPrint`变量为 false，则用户取消了打印作业。由于完全显示对话框是可选的，因此返回的值纯粹是信息性的。

如果`doPrint`变量为 true，则应用程序将通过调用`PrinterJob.print`方法请求打印作业。

```
if (doPrint) {
    try {
        job.print();
    } catch (PrinterException e) {
        // The job did not successfully
        // complete
    }
}

```

如果将作业发送到打印机时出现问题，则会抛出`PrinterException`。但是，由于`PrinterJob.print`方法在作业发送到打印机后立即返回，因此用户应用程序无法检测到卡纸或缺纸问题。该作业控制样板足以用于基本打印用途。

`Printable`接口只有一种方法：

```
public int print(Graphics graphics,
           PageFormat pf, int page)
           throws PrinterException;

```

[`PageFormat`](https://docs.oracle.com/javase/8/docs/api/java/awt/print/PageFormat.html) 类描述页面方向（纵向或横向）及其大小和可成像区域，单位为 1/72 英寸。可成像区域占大多数打印机的边际限制（硬件边距）。可成像区域是这些边距内的空间，实际上，如果通常进一步限制为页眉或页脚留出空间。

`page`参数是将呈现的从零开始的页码。

以下代码表示完整的`Printable`实现：

```
import java.awt.print.*;
import java.awt.*;

public class HelloWorldPrinter
    implements Printable {

  public int print(Graphics g, PageFormat pf, int page)
      throws PrinterException {

    // We have only one page, and 'page'
    // is zero-based
    if (page > 0) {
         return NO_SUCH_PAGE;
    }

    // User (0,0) is typically outside the
    // imageable area, so we must translate
    // by the X and Y values in the PageFormat
    // to avoid clipping.
    Graphics2D g2d = (Graphics2D)g;
    g2d.translate(pf.getImageableX(), pf.getImageableY());

    // Now we perform our rendering
    g.drawString("Hello world!", 100, 100);

    // tell the caller that this page is part
    // of the printed document
    return PAGE_EXISTS;
  }
}

```

此示例的完整代码位于 [`HelloWorldPrinter.java`](examples/HelloWorldPrinter.java) 中。

将 [`Graphics`](https://docs.oracle.com/javase/8/docs/api/java/awt/Graphics.html) 实例发送到打印机与将其呈现到屏幕基本相同。在这两种情况下，您都需要执行以下步骤：

*   绘制测试字符串就像描述绘制到`Graphics2D`所描述的其他操作一样简单。
*   打印机图形具有更高的分辨率，对于大多数代码而言应该是透明的。
*   `Printable.print()`方法由打印系统调用，就像调用`Component.paint()`方法在显示器上绘制 Component 一样。打印系统将调用页面 0,1，...等的`Printable.print()`方法，直到`print()`方法返回`NO_SUCH_PAGE`。
*   在文档完成之前，可以多次使用相同的页面索引调用`print()`方法。当用户使用 collat​​e 选项指定多个副本等属性时，将应用此功能。
*   PageFormat 的可成像区域决定剪辑区域。可计算区域在计算分页或如何跨打印页面跨越内容时也很重要，因为分页符取决于每页可以容纳多少。

    * * *

    **注意：**如果用户指定了不涉及特定页面索引的不同页面范围，则可能会跳过对某些页面索引的`print()`方法调用。

    * * *