前言
在我们的实际工作中经常需要实现打印功能但由于历史原因Java提供的打印功能一直都比较弱实际上最初的jdk根本不支持打印直到jdk才引入了很轻量的打印支持所以在以前用Java/Applet/JSP/Servlet设计的程序中较复杂的打印都是通过调用ActiveX/OCX控件或者VB/VC程序来实现的非常麻烦实际上SUN公司也一直致力于Java打印功能的完善而Java平台则终于有了一个健壮的打印模式的开端该打印模式与JavaD图形包充分结合成一体更令人鼓舞的是新发布的jdk则提供了一套完整的Java 打印服务 API (Java Print Service API)它对已有的打印功能是积极的补充利用它我们可以实现大部分实际应用需求包括打印文字图形文件及打印预览等等本文将通过一个具体的程序实例来说明如何设计Java打印程序以实现这些功能并对不同版本的实现方法进行分析比较希望大家能从中获取一些有益的提示
Java中的打印
Java的打印API
Java的打印API主要存在于javaawtprint包中而jdk新增的类则主要存在于javaxprint包及其相应的子包javaxprintevent和javaxprintattribute中其中javaxprint包中主要包含打印服务的相关类而javaxprintevent则包含打印事件的相关定义javaxprintattribute则包括打印服务的可用属性列表等
如何实现打印
要产生一个打印至少需要考虑两条
需要一个打印服务对象这可通过三种方式实现在jdk之前的版本必须要实现javaawtprintPrintable接口或通过ToolkitgetDefaultToolkit()getPrintJob来获取打印服务对象在jdk中则可以通过javaxprintPrintSerivceLookup来查找定位一个打印服务对象
需要开始一个打印工作这也有几种实现方法在jdk之前可以通过javaawtprintPrintJob(jdk提供的现在已经很少用了)调用print或printAll方法开始打印工作也可以通过javaawtprintPrinterJob的printDialog显示打印对话框然后通过print方法开始打印在jdk中则可以通过javaxprintServiceUI的printDialog显示打印对话框然后调用print方法开始一个打印工作
打印机对话框
Printable的打印对话框
开始打印工作之前可以通过PrinterJobprintDialog来显示一个打印对话框它给用户一个机会以选择应该打印的页码范围并可供用户改变打印设置它是一个本地对话框
事实上当从一个Printable对象进行一个打印工作时打印对象并不知道需要打印多少页它只是不停地调用print方法只要print方法返回PrintablePAGE_EXISTS值打印工作就不停地产生打印页直到print方法返回PrintableNO_SUCH_PAGE时打印工作才停止
由于打印工作只有在打印完成后才进行准确的页数计算所以在对话框上的页码范围是尚未初始化的[]我们可以通过构建一个javaawtprintBook对象传递给打印对象也可以通过指定的格式计算需要打印的页数并传递给打印对象使其准确地知道要打印多少页
ServiceUI的打印对话框
与Printable的对话框不同的是在jdk提供ServiceUI的打印机对话框的缺省行为已经用新的 API 更改了缺省情况下对话框不显示我们必须使用ServiceUI类调用printDialog方法创建如下所示的打印对话框
Java打印程序设计实例
打印文本
应用场景
假设我们需要打印一个窗体的某个文本编辑域(可能只有几行也可能包含多页)的内容并且每页最多打印行如何实现呢?
解决方法
基本思路如下首先我们需要实现Printable接口然后按照每页最多行的格式计算共需要打印多少页当打印文本的按钮被点击时执行相应的打印动作打印文本的具体操作可通过GraphicsD的drawString方法来实现
) 实现Printable接口
/*Graphic指明打印的图形环境PageFormat指明打印页格式(页面大小以点为计量单位点为英寸的/英寸为毫米A纸大致为×点)page指明页号*/
public int print(Graphics g PageFormat pf int page) throws PrinterException {
GraphicsD g = (GraphicsD)g;
gsetPaint(Colorblack); //设置打印颜色为黑色
if (page >= PAGES) //当打印页号大于需要打印的总页数时打印工作结束
return PrintableNO_SUCH_PAGE;
gtranslate(pfgetImageableX() pfgetImageableY());//转换坐标确定打印边界
drawCurrentPageText(g pf page); //打印当前页文本
return PrintablePAGE_EXISTS; //存在打印页时继续打印工作
}
/*打印指定页号的具体文本内容*/
private void drawCurrentPageText(GraphicsD g PageFormat pf int page) {
String s = getDrawText(printStr)[page]; //获取当前页的待打印文本内容
//获取默认字体及相应的尺寸
FontRenderContext context = ggetFontRenderContext();
Font f = areagetFont();
String drawText;
float ascent = ; //给定字符点阵
int k i = fgetSize() lines = ;
while(slength() > && lines < ) //每页限定在行以内
{
k = sindexOf(\n); //获取每一个回车符的位置
if (k != ) //存在回车符
{
lines += ; //计算行数
drawText = ssubstring( k); //获取每一行文本
gdrawString(drawText ascent); //具体打印每一行文本同时走纸移位
if (ssubstring(k + )length() > ) {
s = ssubstring(k + ); //截取尚未打印的文本
ascent += i;
}
}
else //不存在回车符
{
lines += ; //计算行数
drawText = s; //获取每一行文本
gdrawString(drawText ascent); //具体打印每一行文本同时走纸移位
s = ; //文本已结束
}
}
}
/*将打印目标文本按页存放为字符串数组*/
public String[] getDrawText(String s) {
String[] drawText = new String[PAGES]; //根据页数初始化数组
for (int i = ; i < PAGES; i++)
drawText[i] = ; //数组元素初始化为空字符串
int k suffix = lines = ;
while (slength() > ) {
if (lines < ) //不够一页时
{
k = sindexOf(\n);
if (k != ) //存在回车符
{
lines += ; //行数累加
//计算该页的具体文本内容存放到相应下标的数组元素
drawText[suffix] = drawText[suffix] + ssubstring( k + );
if (ssubstring(k + )length() > )
s = ssubstring(k + );
}
else
{
lines += ; //行数累加
//将文本内容存放到相应的数组元素
drawText[suffix] = drawText[suffix] + s;
s = ;
}
}
else //已满一页时
{
lines = ; //行数统计清零
suffix++; //数组下标加
}
}
return drawText;
}
) 计算需要打印的总页数
public int getPagesCount(String curStr) {
int page = ;
int position count = ;
String str = curStr;
while(strlength() > ) //文本尚未计算完毕
{
position = strindexOf(\n); //计算回车符的位置
count += ; //统计行数
if (position != )
str = strsubstring(position + ); //截取尚未计算的文本
else
str = ; //文本已计算完毕
}
if (count > )
page = count / + ; //以总行数除以获取总页数
return page; //返回需打印的总页数
}
以jdk以前的版本实现打印动作按钮监听并完成具体的打印操作
private void printTextAction() {
printStr = areagetText()trim(); //获取需要打印的目标文本
if (printStr != null && printStrlength() > ) //当打印内容不为空时
{
PAGES = getPagesCount(printStr); //获取打印总页数
PrinterJob myPrtJob = PrinterJobgetPrinterJob(); //获取默认打印作业
PageFormat pageFormat = myPrtJobdefaultPage(); //获取默认打印页面格式
myPrtJobsetPrintable(this pageFormat); //设置打印工作
if (myPrtJobprintDialog()) //显示打印对话框
{
try {
myPrtJobprint(); //进行每一页的具体打印操作
}
catch(PrinterException pe) {
peprintStackTrace();
}
}
}
else { //如果打印内容为空时提示用户打印将取消
JOptionPaneshowConfirmDialog(null Sorry Printer Job is Empty Print Cancelled! Empty JOptionPaneDEFAULT_OPTION JOptionPaneWARNING_MESSAGE);
}
}
以jdk新版本提供的API实现打印动作按钮监听并完成具体的打印操作
private void printTextAction() {
printFlag = ; //打印标志清零
printStr = areagetText()trim();