PrintJob、Printable类:
打印主要通过PrintJob类的print的回调函数来实现打印的全部工作。PrintJob类是抽象类,不能new一个实例,但通过它的一个静态方法getPrintJob就可以得到一个PrintJob句柄。有了这样一个操纵杆,我们可以随时打开开关,叫它“快给我打印!”(print),如果这样,它会问你:“叫我打印什么呢?”,即回调你的打印内容,如果你没有打印的内容,它会抛出一句话:“没有东西嘛!”(PrintException)。否则它就会忠实的根据需求打印。
所以你应该提供一个可打印的内容(Printable)。只有一个方法需要你实现:
print(Graphics g , PageFormat pf , int pageIndex );
你所有的打印控制其实都是在该方法中实现。提供一个最简单的例子:
import java.awt.Graphics;
import java.awt.print.*;
public class TestPrint {
public static void main(String[] args) {
PrintJob job = PrintJob.getPrintJob();//获得句柄。
job.setPrintable(new Hello());//告诉job到哪里找打印内容。
try{
job.print();//快给我打印!
}catch(PrintException e) {
System.out.println(“没有东西嘛!”);//或打印机硬件问题。
}
}
class Hello implements Printable {//可打印的内容。
public int print(Graphics g , //可以任意画打印的内容的白纸。
PageFormat pf , // 打印格式,缺省。
int pageIndex ) {// 页码,从0开始。
if(pageIndex != 0 )return NO_SUCH_PAGE;//停止打印。
g.drawString(“Hello World!”,100,100);//在纸上画字符串。
return PAGE_EXITS;//继续打印。
}
}
}
怎么样?够方便吧,发挥你的想象,在Graphics上画你喜欢的东西吧!
PageFormat、Paper类:
在例子中的Printable的print()方法的参数列表中,PageFormat类有点陌生,顾名思义,它是打印的格式。我们在打印过程中选择的横打、纵打,页边距都是由PageFormat控制的,默认的格式是Letter纸,普通的页边距(通过PrintJob的defaultPage得到)。在你得到PageFormat实例后,你可以轻松设置打印的区域(不能直接设置纸张的大小)、打印方向。如何改变纸张的大小呢?java自带的页面设置有几种典型的纸张类型(A4、A3等),如果要自定义纸张大小,从PageFormat实例中的getPaper()方法获得名为Paper的实例,再通过Paper的setSize()改变纸张实际大小。讲了这么多,看一个例子:
import java.awt.*;
import java.awt.print.*;
public class TestFormat {
public static void main(String[] args) {
PrinterJob job = PrintJob.getPrinterJob();
PageFormat pageFormat = job.defaultPage();//得到默认页格式
double inch = 72;//一英寸
Paper paper = pageFormat.getPaper();//得到页面格式的纸张
paper.setSize(5 * inch,5 * inch);//纸张大小为5英寸见方
pageFormat.setImageableArea(
inch,//坐标x,即左页边距1英寸
inch,//坐标y,即上页边距1英寸
paper.getWidth() - 2 * inch,//宽度,5英寸-2英寸(左右各1英寸)
paper.getHeight() - 2 * inch);//高度,5英寸-2英寸(上下各1英寸)
pageFormat.setPaper(paper);//将该纸张作为格式
job.setPrintable(new Rect(),pageFormat);//不止提供打印内容,还有格式
if(job.printDialog()) {//熟悉的打印设置对话框,OK返回true,Cancel返回false
try{
job.print();
}catch(PrinterException e){
System.out.println(e);
}
}
}
class Rect implements Printable {
public int print(Gaphics g,PageFormat pageFormat,int pageIndex) {
if(pageIndex != 0)return NO_SUCH_PAGE;
g.fillRect(0,0,100,100);//画一个100的正方形
return PAGE_EXISTS;
}
}
}
相对于TestPrint.java,现在的例子复杂多了,所有新添加的内容都有注释,本来想打印100的正方形,但当你兴冲冲去取打印结果时,你只能得到一个小的多的正方形(实际上有100 - 72 = 28那么大)。因为你是从纸的左上角开始画,但有一英寸的页边距让你的构想变小了。
如果你打印的东西是统一格式的(大部分情况都是如此),打印就变得如此简单,关键是你在纸上画的东西根据页码(pageIndex)的不同能打印不同的东西。
血的教训:千万在实现的print()方法中加入控制打印结束的语句(NO_SUCH_PAGE),否则打印机会孜孜不倦的打到它打不动位置。我的抽屉内还有十几张打印机的杰作,如果不是我强行关闭电源,它的发挥远不止这些。
预览类的构造函数是这样的:
public PrintPreviewer(Pageable p,int page){
pageable=p;
pageIndex=page;
printComponent=new PrintComponent(null,null);
printComponent.setBorder(BorderFactory.createBevelBorder(
BevelBorder.RAISED));
buildLayout();
displayPage(pageIndex);
}
protected void buildLayout(){
setLayout(new BorderLayout());
JPanel panel=new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.CENTER,10,10));
panel.add(printComponent);
scrollPane=new JScrollPane(panel);
add(scrollPane,BorderLayout.CENTER);
add(getBottomPanel(),BorderLayout.SOUTH);
addListeners();
}