文档

Java™教程
隐藏目录
如何打印文本
路径: 使用Swing创建GUI
教程: 使用其他Swing特性

如何打印文本

JTextComponent类提供了文本文档打印的支持。 JTextComponent API包括了允许您实现基本和高级打印任务的方法。支持的格式包括HTML、RTF和纯文本。对于简单的打印任务,比如打印文本文档,可以直接使用print方法。 print方法有几种形式,具有不同的参数集。该方法准备您的文本文档,获取相应的Printable对象,并将其发送到打印机。

如果默认的Printable对象的实现不符合您的需求,您可以通过覆盖getPrintable方法来自定义打印布局,以包装默认的Printable对象,甚至完全替换它。

打印文本组件的最简单方法是调用没有参数的print方法。请参阅下面的代码示例。

try {
   boolean complete = textComponent.print();
   if (complete) {
       /*显示成功消息*/
       ...
   } else {
       /*显示打印被取消的消息*/
       ...
   }
} catch (PrinterException pe) {
   /*打印失败,向用户报告*/
   ...
}

当您调用没有参数的print方法时,将显示打印对话框,然后以交互方式打印您的文本组件,不包括页眉和页脚。下面的代码示例显示了具有完整参数集的print方法签名。

boolean complete = textComponent.print(MessageFormat headerFormat,
                                      MessageFormat footerFormat, 
                                      boolean showPrintDialog,
                                      PrintService service
                                      PrintRequestAttributeSet attributes,
                                      boolean interactive);

当您使用所有参数调用print方法时,您可以显式选择打印特性,例如页眉和页脚文本、打印属性、目标打印服务,以及是否显示打印对话框,以及是否交互式或非交互式打印。要决定哪些参数最适合您的需求,请参阅下面的可用特性的描述。

JTextComponent打印API提供了以下功能:

交互式或非交互式打印

在交互模式下,打印过程中会显示一个带有中止选项的进度对话框。以下是一个进度对话框的示例。

打印进度对话框的屏幕截图

该对话框允许用户跟踪打印进度。当在事件调度线程上调用print方法时,进度对话框是模态的;否则是非模态的。在打印过程中,文档必须保持不变,否则打印行为是未定义的。print方法确保文档不会被更改,并在打印过程中禁用组件。

如果您在非交互模式下在事件调度线程上调用print方法,那么所有事件,包括重绘,都将被阻塞。因此,只建议在具有非可见GUI的应用程序上在EDT上进行非交互式打印。

打印对话框

您可以显示一个标准的打印对话框,用户可以在该对话框中执行以下操作:

打印对话框的屏幕截图

您可能注意到打印对话框中没有指定打印输出中的总页数。这是因为文本打印实现使用了Printable API,并且在打印时无法知道总页数。

向打印布局添加页眉、页脚(或同时添加)

页眉和页脚是由MessageFormat参数提供的。这些参数允许对页眉和页脚进行本地化。请阅读MessageFormat类的文档,因为特殊字符(如单引号)需要避免使用。页眉和页脚都居中显示。您可以使用{0}插入页码。

MessageFormat footer = new MessageFormat("页码 - {0}");

由于在输出时无法事先知道输出的总页数,因此无法指定类似“第1页/共5页”的编号格式。

自动布局和分页

使用JTextComponent打印API时,您无需关心布局和分页。布局和分页都会自动完成。文档内容会被格式化以适应页面大小,并跨多个页面显示。如果您希望在页脚中插入页码,只需向print方法指定适当的页脚文本格式即可。如前所示,您可以通过在提供给MessageFormat页脚参数的字符串中包含"{0}"来指定页码。在打印输出中,{0}将被当前页码替换。

文本区打印示例

让我们来看一个名为TextAreaPrintingDemo的示例。该示例的主要特点是根据用户的选择,在事件分派线程或后台线程上打印文本文档。该示例显示一个文本区,允许选择几个打印功能,并根据所选选项打印文本区的内容。完整的程序代码可以在TextAreaPrintingDemo.java中找到。该示例的GUI使用NetBeans IDE GUI构建器构建。下面是TextAreaPrintingDemo应用程序的截图。

TextAreaPrintingDemo的截图

试一下这个:
  1. 点击“启动”按钮,使用Java™ Web Start 运行TextAreaPrintingDemo(下载JDK 7或更高版本)。或者,如果你想自己编译和运行示例,请参考示例索引启动TextAreaPrintingDemo应用程序
  2. 编辑“页眉”和“页脚”复选框中的文本,以提供不同的页眉或页脚。
  3. 如果你想在打印时不显示进度对话框(即非交互式打印),请取消选中“显示进度对话框”复选框。请注意,一旦开始打印,就无法取消打印。
  4. 取消选中“在后台打印”复选框以选择在事件分派线程上打印。请注意,非交互式打印将使你的应用程序无响应-在打印过程中将阻塞与应用程序的交互。
  5. 点击“打印”按钮,根据所选选项打印文本区域的内容。

每当一个通过Web启动的应用程序尝试打印时,Java Web Start都会打开一个安全对话框,询问用户是否允许打印,除非该权限已在系统设置中授予。要继续打印,用户必须接受该请求。

为“打印”按钮注册了一个动作监听器。当用户点击“打印”按钮时,actionPerformed方法调用print方法,启动一个打印任务。打印任务是一个SwingWorker对象。下面的代码示例显示了PrintingTask类的实现。

private class PrintingTask extends SwingWorker<Object, Object> {
    private final MessageFormat headerFormat;
    private final MessageFormat footerFormat;
    private final boolean interactive;
    private volatile boolean complete = false;
    private volatile String message;
        
    public PrintingTask(MessageFormat header, MessageFormat footer,
                        boolean interactive) {
        this.headerFormat = header;
        this.footerFormat = footer;
        this.interactive = interactive;
    }
        
    @Override
    protected Object doInBackground() {
        try {
            complete = text.print(headerFormat, footerFormat,
                    true, null, null, interactive);
            message = "打印" + (complete ? "完成" : "已取消");
        } catch (PrinterException ex) {
            message = "抱歉,发生打印机错误";
        } catch (SecurityException ex) {
            message = "抱歉,由于安全原因无法访问打印机";
        }
        return null;
    }
        
    @Override
    protected void done() {
        message(!complete, message);
    }
}

下面的代码示例显示了print方法如何从GUI组件中获取所选选项集,然后创建PrintingTask类的实例并执行打印。

private void print(java.awt.event.ActionEvent evt) {
        MessageFormat header = createFormat(headerField);
        MessageFormat footer = createFormat(footerField);
        boolean interactive = interactiveCheck.isSelected();
        boolean background = backgroundCheck.isSelected();

        PrintingTask task = new PrintingTask(header, footer, interactive);
        if (background) {
            task.execute();
        } else {
            task.run()
        }
    }

粗体显示的代码演示了如何根据background参数的值调用PrintingTask的方法。每当用户选择在后台线程上打印时,将调用execute方法,该方法将打印任务安排在后台线程上执行。否则,run方法将在EDT上执行打印任务。

由于打印大型文档是一个耗时的任务,建议在后台线程上执行打印。

文本批量打印示例

TextBatchPrintingDemo示例演示了如何在后台线程上打印非可见的HTML文本文档。启动此演示时,会显示一个包含URL列表的页面。您可以访问一个HTML页面,将显示的页面添加到打印列表中,并在选择所需的所有页面后一次性在后台线程上打印它们。此程序的全部代码可以在TextBatchPrintingDemo.java中找到。这是TextBatchPrintingDemo应用程序的图片。

TextBatchPrintingDemo的屏幕截图

尝试这样做:
  1. 点击“启动”按钮以使用Java™ Web Start运行TextBatchPrintingDemo(下载JDK 7或更高版本)。或者,要自己编译和运行示例,请参考示例索引启动TextBatchPrintingDemo应用程序
  2. 点击任意链接以查看相应的HTML页面。
  3. 按下ALT+A或选择“文件”>“添加页面”菜单项将显示的页面添加到右侧的打印列表中。
  4. 按下ALT+H或选择“文件”>“主页”菜单项返回到演示的主页。
  5. 根据需要将页面添加到打印列表中。
  6. 按下ALT+C或选择“文件”>“清除所选”菜单项,如果需要清除打印列表并重新构建。
  7. 按下ALT+P或选择“文件”>“打印所选”菜单项以打印所选页面。
  8. 按下ALT+Q或选择“文件”>“退出”菜单项以退出应用程序。

您可以在printSelectedPages方法中找到打印代码。调用此方法时,首先获取选择的打印页面数量。下面的代码示例显示了printSelectedPages方法如何为每个页面创建一个Runnable对象,然后在单独的线程上打印当前页面。

for (int i = 0; i < n; i++) {
    final PageItem item = (PageItem) pages.getElementAt(i);
    // 此方法从EDT中调用。打印是一项耗时的任务,因此应该在EDT之外,在单独的线程中进行。
    Runnable printTask = new Runnable() {
        public void run() {
            try {
                item.print(
                        // 两个“false”参数表示“无打印对话框”和“非交互式”(即批处理模式打印)。
                                null, null, false, printService, null, false);
            } catch (PrinterException pe) {
                JOptionPane.showMessageDialog(null,
                        "打印" + item.getPage() + "时出错\n" + pe,
                        "打印错误", JOptionPane.WARNING_MESSAGE);
            }
        }
    };
    new Thread(printTask).start();

文本打印API

本节列出了JTextComponent类中定义的允许您打印文本文档的方法。

方法 目的
boolean print()
boolean print(MessageFormat, MessageFormat)
boolean print(MessageFormat, MessageFormat, boolean, PrintRequestAttributeSet, boolean, PrintService)
当无参数调用时,显示打印对话框,并以交互方式打印此文本组件,无页眉或页脚文本。如果用户继续打印,则返回true,如果用户取消打印,则返回false
当使用两个MessageFormat参数调用时,显示打印对话框,并以指定的页眉和页脚文本交互打印此文本组件。
当使用完整的参数集调用时,根据指定的参数打印此文本组件。两个MessageFormat参数指定页眉和页脚文本。第一个布尔参数定义是否显示打印对话框。另一个布尔参数指定是否交互式打印。通过另外两个参数,您可以指定打印属性和打印服务。
每当省略PrintService参数时,将使用默认打印机。
Printable getPrintable(MessageFormat, MessageFormat) 返回一个用于打印文本组件的Printable对象。重写此方法以获取自定义的Printable对象。您可以将一个Printable对象包装在另一个对象中,以获得复杂的报告和文档。

使用文本打印的示例

此表列出了使用文本打印的示例,并指向这些示例所在的位置。

示例 描述位置 备注
TextAreaPrintingDemo 此页面 演示了文本打印的基础知识,并提供了丰富的GUI。允许用户指定页眉或页脚文本,打开或关闭打印对话框,选择交互式或非交互式打印,然后根据所选选项进行打印。
TextBatchPrintingDemo 此页面 此演示显示了一个带有URL列表的文本组件,允许用户查看HTML页面,将其添加到打印列表,并一次在后台线程上打印所有选定的页面。

上一页: 如何打印表格
下一页: 如何创建启动画面