有关在Java中实现文档打印的典型说法描述了一个复杂的过程,它要求对字 体进行测定、对文本进行解析并将结果绘制到一个Graphics对象中。这个过程似 乎执行起来相当困难,并且它和用于文档视频显示的高级编程方法不一致。如果 你想要花费大量的精力来完成这个过程,那么你就不会首先想到要在Java中编程 。
你一定不想自己完成测定、解析和绘制过程,而是希望通过简单地将文档发 送到一个能为你处理所有事情的对象中来完成这个任务。本文就将介绍这样一个 对象――DocumentRenderer,它将一个文档作为方法中的一个参数并处理指定任 务来完成打印。比如,用这个类来显示一个HTML文档需要两个步骤:构造一个 DocumentRenderer类的实例并将HTML文档作为参数发送到print(HTMLDocument) 方法中。DocumentRenderer类用于处理打印该文档所必需的开销,包括显示一个 打印对话框以及格式化文本。
我们设计了这个DocumentRenderer类以便利用这个已经在Java中可用的高级 文本性能。 根据可重用和可扩展类的原则,我们使用了一些现有的对象 (Java.Swing.Text Package用它来对显示结果进行格式化)使打印结果能够显 示在纸上。用这种方法设计DocumentRenderer使我们能够用比前面讨论过的方法 少写近200行的代码来建立这个类。
除了能少写代码之外,使用DocumentRenderer 实现中的现有对象还提供了一 些额外的功能使得该类更加通用。在最初设计这个类的时候,我们只是打算将 HTML文档打印出来。而添加一些功能来打印其他类型的文档则是后来的想法。当 我们发现只需在用于HTML 打印类的代码中加上约6行的额外代码就可以打印一个 Rich Text Format文档时,便在这个项目的后期添加了这个功能。
显示文档
DocumentRenderer能够用来打印几类包含在JEditorPane中的文档。我们用三 种类型的文档(JEditorPane能够缺省识别的)测试了这个printer类: HTMLDocuments、PlainDocuments和Rich Text Format文档。只需要做一些很小 的改动,这个类就应该可以将包含在JEditorPane中的其他类型文档打印出来了 。
DocumentRenderer类将一个文档的打印形式从其视频显示中区分出来了。这 就使你能够针对特定的打印结果进行文本格式化,而会不影响其屏幕显示。 DocumentRenderer采用所有打印页面的实际大小来显示文本并计算出行间距 (line break)。当文档的宽度不足以显示在打印页面上时,该类会允许使用缩 放(scaling)。
DocumentRenderer相当智能。分页符不会将一行单一语句分放到两个页面上 。字符也不会被切成两半,不会象浏览器在处理一般打印时会在这一页末尾显示 一句话的上半部分而在下一页的顶部显示这句话的下半部分。这个类能够处理大 量字体、颜色和小图标。分栏文本的显示也没有问题。对于每一个JEditorPane 能够显示的文本特性,通常DocumentRenderer都可以将这种性能呈现到纸上。
你只需使用两行代码便可以将DocumentRenderer结合到你的程序中去了。用 一个不带参数的构造器创建这个类的实例,再调用一个合适的打印方法来处理其 他事情。比如,以下代码将打印这个htmlDocument,它是HTMLDocument类的一个 有效实例:
DocumentRenderer DocumentRenderer = new
DocumentRenderer();
DocumentRenderer.print(htmlDocument);
它给用户显示一个打印对话框,允许用户选择打印机、打印数量等,同时还 有一个取消打印的选项。
PlainDocuments使用了print(PlainDocument)方法,采用和HTMLDocuments相 同的方式执行打印。由于在Java中不能直接访问Rich Text Format文档,所以你 必须将这种类型的文档发送到DocumentRenderer中(通过将它封装到一个 JEditorPane里),就象这样:DocumentRenderer.print(jeditorPane);
这里的jeditorPane是JEditorPane的一个有效实例,其中包含一个Rich Text Format文档。
为了给用户提供方便,你可以调用DocumentRenderer的pageDialog方法来显 示一个打印对话框以便用户可以调整页面大小、页边设置和纸的打印方向 (orientation)。DocumentRenderer还提供了一种方法使开发人员可以选择是 否对那些无法在打印宽度内完全显示的文档进行按比例缩放。我们认为能够进行 缩放通常是比较好的选择,因为它能够防止文本在正确的页边处被分开,但它似 乎比较适合让用户去选择。这种名为setScaleWidthToFit(boolean)的方法提供 了按比例缩放的选项。你必须确定在调用打印方法之前调用这个scaling和 pageDialog方法。
了解DocumentRenderer
DocumentRenderer用于执行显示一个打印对话框并通过使用在Java Swing Printing API中可用的标准化工具开始打印操作。由于在使用这个 DocumentRenderer类时无需完全了解这个API,而且该API已经在很多地方被详细 描述过,因此这里我们就不再介绍它了。这个用于DocumentRenderer类的源代码 中还包括了这个打印逻辑的完整文档。
然而我们或许应该解释一下DocumentRenderer用来在单独打印页面中定位文 本的过程,以便你了解这个类所提供的改进功能,这会帮你回顾这个Java打印过 程通常遵循的显示文档的逻辑。
文档通常是以一种简单的方式进行打印的。首先,文档会被放入JEditorPane 。你可以将打印过程想象为在JEditorPane 的上面放置一个矩形框(其大小和页 面打印区的大小相等),并对其中的内容进行打印而无需关心外面的部分。
这个矩形的上沿与JEditorPane 顶部齐平,矩形框内部的区域会被绘制 (paint)。如果矩形的下沿穿过文本,不用去管它;字符会在打印页面的底部 被分开。打印第二页时,矩形的上沿被向下移至前面被下沿所占据的那一行,该 过程被重复执行。由于第二页正好在第一页结束的地方开始,因此在第一页底部 被分开的字符会出现在第二页的顶部。后面几页也是一样。
为了避免从行中断开,DocumentRenderer会仔细检侧文档以测定是否一个单 独文本和页面完整契合。这样会比只是在JEditorPane中放一个矩形框并打印其 中内容的效果更佳。