这些 Java 教程是针对 JDK 8 编写的。本页面中描述的示例和实践不利用后续版本中引入的改进,并且可能使用不再可用的技术。
请参阅 Java 语言更改,了解 Java SE 9 及其后续版本中更新的语言特性的摘要。
请参阅 JDK 发布说明,了解有关所有 JDK 发布的新功能、增强功能以及已删除或弃用选项的信息。
JTable类提供对表格的打印支持。 JTable打印API包括了允许您实现基本和高级打印任务的方法。 对于常见的打印任务,当您只需要打印一个表格时,直接使用print方法即可。 print方法有多种形式,具有不同的参数集。 该方法准备您的表格,获取相应的Printable对象,并将其发送到打印机。
如果Printable对象的默认实现不符合您的需求,您可以通过重写getPrintable方法来自定义打印布局,以包装默认的Printable对象或完全替换它。
打印表格的最简单方法是调用没有参数的print方法。 请参阅下面的代码示例。
try {
boolean complete = table.print();
if (complete) {
/* 显示成功消息 */
...
} else {
/* 显示打印被取消的消息 */
...
}
} catch (PrinterException pe) {
/* 打印失败,向用户报告 */
...
}
当您调用没有参数的print方法时,将显示打印对话框,然后以FIT_WIDTH模式交互式打印您的表格,不包括页眉和页脚。 以下代码示例显示了带有完整参数集的print方法签名。
boolean complete = table.print(JTable.PrintMode printMode,
MessageFormat headerFormat,
MessageFormat footerFormat,
boolean showPrintDialog,
PrintRequestAttributeSet attr,
boolean interactive,
PrintService service);
当您使用所有参数调用print方法时,您可以明确选择打印功能,例如打印模式、页眉和页脚文本、打印属性、目标打印服务,以及是否显示打印对话框,以及是否交互式打印。 要确定哪些参数最适合您的需求,请参阅下面可用功能的描述。
JTable打印API提供以下功能:
在交互模式下,将显示一个带有中止选项的进度对话框,用于打印的持续时间。 下面是一个进度对话框的示例。
该对话框允许用户跟踪打印进度。进度对话框是模态的,这意味着在显示对话框时,用户无法与表格进行交互。在打印期间,重要的是您的表格保持不变,否则打印行为将是未定义的。然而,交互式打印不会阻止其他开发者的代码修改表格。例如,还有另一个线程使用SwingUtilities.invokeLater方法发布更新。因此,为确保正确的打印行为,您应确保在打印期间您自己的代码不会修改表格。
或者,您可以以非交互方式打印表格。在这种模式下,打印立即在事件调度线程上开始,并完全阻塞任何待处理的事件。一方面,这种模式可以确保在打印完成之前,表格不会发生任何更改。另一方面,这种模式完全剥夺了用户与GUI的任何交互。这就是为什么只有在从非可见GUI的应用程序打印时才推荐使用非交互打印。
您可以显示一个标准的打印对话框,允许用户执行以下操作:
您可能会注意到打印对话框中没有指定打印输出的总页数。这是因为表格打印实现使用了Printable API,打印时无法预先知道总页数。
页眉和页脚由MessageFormat参数提供。这些参数允许对页眉和页脚进行本地化。请阅读MessageFormat类的文档,因为一些字符(例如单引号)是特殊字符,需要避免使用。页眉和页脚都居中。您可以使用{0}插入页码。
MessageFormat footer = new MessageFormat("Page - {0}");
由于在打印时不知道输出的总页数,因此无法指定像“第1页/共5页”这样的编号格式。
打印模式负责缩放输出并将其分布在页面上。您可以以以下任一模式打印表格:
PrintMode.NORMAL(正常模式)PrintMode.FIT_WIDTH(适应宽度模式)在NORMAL模式下,表格以其当前大小打印。如果列无法适应一页,它们将根据表格的ComponentOrientation分布在其他页面上。在FIT_WIDTH模式下,如果需要,表格的大小会缩小以适应每页的所有列。请注意,宽度和高度都会按比例缩放,以提供相同比例的输出。在这两种模式下,行会依次跨多个页面展开,每页尽可能多的行。
使用JTable打印API,您无需关心布局和分页。您只需要为print方法指定适当的参数,例如打印模式和页脚文本格式(如果您想在页脚插入页码)。如前所示,您可以在页脚字符串中包含"{0}"来指定页码。在打印输出中,{0}将被当前页码替换。
让我们来看一个名为TablePrintDemo1的示例。该程序的完整代码可以在TablePrintDemo1.java中找到。这个演示的丰富GUI是由NetBeans IDE GUI构建器自动构建的。这是TablePrintDemo1应用程序的截图。
每当一个通过Web启动的应用程序尝试进行打印时,Java Web Start会弹出一个安全对话框,询问用户是否允许打印。要继续打印,用户必须接受请求。
请注意,当你清除“交互式”复选框时,会出现一个警告消息,提醒用户打印非交互式的劣势。你可以在PrintGradesTable方法中找到打印代码。当调用此方法时,首先从GUI组件中获取选定选项的集合,然后调用print方法,如下所示。
boolean complete = gradesTable.print(mode, header, footer,
showPrintDialog, null,
interactive, null);
print方法返回的值被用来显示成功消息或用户取消打印的消息。
另一个重要的功能是表格打印API使用表格渲染器。通过使用表格的渲染器,API提供了一个打印输出,其外观与屏幕上的表格相同。看一下屏幕上表格的最后一列。它包含了每个学生的通过或不通过状态的自定义图像。现在看一下打印结果。你会发现,勾号和叉号看起来是一样的。
下面是TablePrintDemo1在FIT_WIDTH模式下的打印结果的图片。
TablePrintDemo2示例是基于上一个示例的,并且具有相同的界面。唯一的区别在于打印输出结果。如果你仔细观察TablePrintDemo1的打印结果,你可能会注意到勾号和X号模糊不清。TablePrintDemo2示例展示了如何自定义表格以使图像在表格打印中更加清晰可辨。在此示例中,重写的getTableCellRendererComponent方法判断表格是否正在打印,并返回更清晰的黑白图像。如果表格没有在打印,它返回在屏幕上可见的彩色图像。
点击“启动”按钮使用Java™ Web Start(下载JDK 7或更高版本)运行TablePrintDemo2。或者,要自己编译和运行示例,请参考示例索引。
JComponent类中定义的isPaintingForPrint方法允许我们根据打印和屏幕显示的差异来自定义打印内容。下面是自定义单元格渲染器的代码,取自TablePrintDemo2.java。这段代码根据isPaintingForPrint方法的返回值选择使用哪些图像。
/**
* 一个自定义单元格渲染器,继承自TablePrintDemo1的渲染器,用于在打印时使用更清晰的黑白图标。
*/
protected static class BWPassedColumnRenderer extends PassedColumnRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
/* 如果当前正在打印,则使用黑白图标 */
if (table.isPaintingForPrint()) {
boolean status = (Boolean)value;
setIcon(status ? passedIconBW : failedIconBW);
} /* 否则,使用父类(彩色)图标 */
return this;
}
}
这是TablePrintDemo2打印结果的图片,使用FIT_WIDTH模式。
TablePrintDemo3示例基于前两个演示。此示例展示了如何通过包装默认的Printable来提供自定义的Printable实现。此演示具有类似的界面,但标题和页脚的复选框被禁用,因为自定义的可打印对象将提供自己的标题和页脚。
点击“启动”按钮使用Java™ Web Start 运行TablePrintDemo3(下载JDK 7或更高版本)。或者,要自己编译和运行示例,请参考示例索引。
此示例将表格打印在剪贴板的图像内。这是TablePrintDemo3示例的打印结果的图片,使用FIT_WIDTH模式。
此程序的完整代码可以在TablePrintDemo3.java中找到。在此演示中,使用了一个名为FancyPrintingJTable的JTable类的自定义子类。这个FancyPrintingJTable类重写了getPrintable方法,返回一个自定义的可打印对象,该对象包装了默认的可打印对象,并带有自己的装饰、标题和页脚。下面是getPrintable方法的实现。
public Printable getPrintable(PrintMode printMode,
MessageFormat headerFormat,
MessageFormat footerFormat) {
MessageFormat pageNumber = new MessageFormat("- {0} -");
/* 获取默认的可打印对象 */
Printable delegate = super.getPrintable(printMode, null, pageNumber);
/* 返回一个包装默认可打印对象的精美可打印对象 */
return new FancyPrintable(delegate);
}
FancyPrintable类负责将默认的可打印对象包装成另一个可打印对象,并设置剪贴板图像。当实例化这个类的一个实例时,它会加载组装剪贴板图像所需的图像,计算剪贴板图像所需的区域,计算表格的缩小区域,将表格打印到较小的区域,并组装和打印剪贴板图像。
请注意,组装剪贴板图像的代码对于页面大小的灵活性。代码考虑了实际页面的尺寸,并组合辅助图像,根据需要拉伸其中一些图像,以使最终的剪贴板图像适合实际页面大小。下图显示了辅助图像并指示这些图像如何组成最终的输出。
本节列出了JTable类中定义的允许您打印表格的方法。
| 方法 | 目的 |
|---|---|
| boolean print() boolean print(printMode) boolean print(printMode, MessageFormat, MessageFormat) boolean print(printMode, MessageFormat, MessageFormat, boolean, PrintRequestAttributeSet, boolean) boolean print(printMode, MessageFormat, MessageFormat, boolean, PrintRequestAttributeSet, boolean, PrintService) |
当不带参数调用时,显示一个打印对话框,然后以FIT_WIDTH模式打印此表格,不包含页眉和页脚文本。如果用户继续打印,则返回true,如果用户取消打印,则返回false。当使用完整的参数列表调用时,根据指定的参数打印此表格。第一个参数指定打印模式。两个 MessageFormat参数指定页眉和页脚文本。第一个布尔参数定义是否显示打印对话框。另一个布尔参数指定是否进行交互式打印。使用另外两个参数,您可以指定打印属性和打印服务。每当省略一个 PrintService参数时,将使用默认打印机。 |
| Printable getPrintable(PrintMode, MessageFormat, MessageFormat) | 返回用于打印表格的Printable对象。重写此方法以获取自定义的Printable对象。您可以将一个Printable对象包装在另一个中以获得各种布局。 |
这个表格列出了使用表格打印的示例,并指向了这些示例所描述的位置。
| 示例 | 描述位置 | 注释 |
|---|---|---|
TablePrintDemo |
如何使用表格 | 演示了表格打印的基本功能,例如显示打印对话框,然后以FIT_WIDTH模式进行交互式打印,并将页码作为页眉。 |
TablePrintDemo1 |
本页面 | 演示了表格打印的基础知识,并提供了一个丰富的GUI。允许用户指定页眉或页脚文本,选择打印模式,打开或关闭打印对话框,以及选择交互式或非交互式打印。 |
TablePrintDemo2 |
本页面 | 基于TablePrintDemo1,此示例具有相同的界面。此演示演示了如何自定义表格,使打印结果与屏幕上显示的表格不同。 |
TablePrintDemo3 |
本页面 | 此演示显示了高级表格打印功能,例如将默认表格可打印对象包装到另一个可打印对象中,以获得不同的布局。 |