用JAVA设计面向对象的打印程序

用JAVA设计面向对象的打印程序

 

转自:http://www.ibm.com/developerworks/cn/java/l-oojavaprint/

张来东 (zhangld@mail.hf.ah.cn)中国人民银行六安市中心支行

2002 年 12 月 09 日

在采用JAVA设计打印程序时仍然可采用结构化的方法,但是编写较为麻烦且代码不能重用,不是一种好的方法,给人一种“新瓶老酒”的感觉。如果将打印内容进行对象化分析,设计出面向对象的打印程序,则会更出色地完成打印要求,并且代码很容易重用,事半功倍。

打印程序的编写通常采用结构化的编程的方法,按特定的位置和一定顺序将打印内容送往打印机。在采用JAVA设计打印程序时仍然可采用结构化的方法,但是编写较为麻烦且代码不能重用,不是一种好的方法,给人一种"新瓶老酒"的感觉。目前为数不少的JAVA书籍在介绍打印时,侧重介绍打印功能的实现,而打印用例的主要代码却是结构化的。java网站在介绍java打印功能时,实现打印的代码也是结构化的。

如果将打印内容进行对象化分析,设计出面向对象的打印程序,则会更出色地完成打印要求,并且代码很容易重用,事半功倍。(本文假定你已经了解java的打印功能)

打印对象的分析

 

打印通常包含以下基本内容:文字、线条、线框、图像等。比如一个表格是由若干文字、线条和线框对象其组成。为叙述简单,本文仅涉及以下三种对象。

文字对象的属性:文字内容,坐标,颜色,字体,对齐方式。

线条对象的属性:起点坐标,终点坐标,颜色,线宽。

线框对象的属性:左上角坐标,宽度,高度,线宽,颜色。

这些打印对象必须能根据属性将自己绘制出来。从另一个层面,可将打印的一页内容,理解为这些打印对象的容器。设计打印程序,只需将打印内容分解成适当的对象,由这些打印对象的集合来完成打印的要求。例如:打印普通表格。只需将表格分解成若开线框对象,线条对象,和文字对象。





打印对象的设计

 

设计思路:根据打印对象的分析,可以将打印的内容看成这些打印对象的集合。实际的打印就是将打印对象集合中的打印对象遍历,调用其print方法,因此这几类打印对象就需要封装相同的打印接口。

1、对象打印接口设计如下:

package lilidb;
import java.awt.Graphics;
/**
*打印对象接口;
*一、文字对象。二、线条对象。三、线框对象。每
*种对象各有其属性,但都必须有print方法。
*/
public interface PrintObject{
    /**
    *打印或预览实际内容
    *@param g   打印或预览的图形对象,根据是预览还是打印传入具体的Graphics对象
    */
    public void print(Graphics g);
}

2、 文字打印对象的设计

为了叙述的简单,文中的打印对象,未加居中等处理。

package lilidb;
import java.awt.*;
import java.util.*;
/**
*打印文字对象
**/
public class PrintLabel implements PrintObject{
    String label;
    int px;
    int py;
    Color color = Color.black;
    FontMetrics fm;
    /**
    *构造PrintLabel 对象,
    *@param ls  标签内容。
    *@param x   标签的X坐标
    *@param y   标签的Y坐标
    */
    public PrintLabel(String ls,int x,int y){
      label = ls;
      px = x;
      py = y;
      range = 1;
    }
    /**
    * 设置颜色
    * @para colr  颜色值
    */
    public void setRange(Color colr){
      color = colr;
    }
    /**
    *设置标签字体
    *@param fontn   字体名称
    *@param type    字体类型 可选值为 Font.BOLD,Font.ITALIC,Font.PLAIN
    *@param size    字体象素尺寸
    */
    public void setFont(String fontn,int type,int size){
        font = new Font(fontn,type,size);
    }
    /**
    *设置标签位置
    *@param x   x坐标
    *@param y y坐标
    */
    public void setLabelPosition(int x,int y){
        px = x;
        py = y;
    }
    /**
    *设置标签内容
    *@param ls  标签内容
    */
    public void setLabelString(String ls){
        label = ls;
    }
    /**
    *打印或预览实际内容
    *@param g   打印或预览的图形对象
    */
    public void print(Graphics gg){
        Graphics2D g = (Graphics2D)gg;
        g.setFont(font);
        g.drawString(label, px, py)
        }
    }
}

3、 线条打印对象的设计

package lilidb;
import java.awt.*;
import java.util.*;
import java.awt.Graphics2D;
import java.awt.Graphics;
/**
*线打印对象
*主要打印线条,其打印位置、和线形可以设置
*/
public class PrintLine implements PrintObject{
    /**
    *线的起点
    */
    int startX;
    int startY;
    /**
    *线的终点
    */
    int endX;
    int endY;
    /**
    *线长
    */
    int lineLong;
    /**
    *线宽
    */
    float lineWidth;
    BasicStroke bs;
    /**
    *构造线对象,确定位置
    *@param sx  线起点X坐标
    *@param sy  线起点Y坐标
    *@param ex  线终点X坐标
    *@param ey  线终点Y坐标
    */
    public PrintLine(int sx,int sy,int ex,int ey){
        startX = sx;
        startY = sy;
        endX = ex;
        endY = ey;
    }
    /**
    *设置线宽
    *@param w   线的宽度
    */
    public void setWidth(float w){
        lineWidth = w;
        bs  = new BasicStroke(lineWidth);
    }
    /**
    *@see PrintObject#print
    */
    public void print(Graphics g){
        Graphics2D g2d = (Graphics2D)g;
        g2d.setStroke(bs);
        g2d.drawLine(startX, startY, endX, endY);
    }
}

4、线框打印对象的设计

package lilidb;
import java.awt.*;
import java.awt.print.*;
import java.util.*;
/**
*打印矩形对象,矩形对象一般用来组成表格,
*/
public class PrintRectangle implements PrintObject{
    float lineWidth;
    BasicStroke bs;
    /**
    *3D矩形
    */
    public final static int REC3D = 0;
    /**
    *普通矩形
    */
    public final static int RECNORMAL = 1;
    /**
    *圆角矩形
    */
    public final static int RECROUND = 2;
    int px;
    int py;
    int w;
    int h;
    /**
    * x 方向圆倒角直径
    */
    int ax;
    /**
    * y 方向圆倒角直径
    */
    int ay;
    int type;
    boolean raised;
    /**
    *设置线宽
    *@param w   线的宽度
    */
    public void setWidth(float w){
        lineWidth = w;
        bs  = new BasicStroke(lineWidth);
    }
    /**
    *构造矩形打印对象
    *@param x   矩形左上角 X 坐标
    *@param y   矩形左上角 y 坐标
    *@param width   矩形宽
    *@param height  矩形高
    */
    public PrintRectangle(int x,int y,int width ,int height){
        px = x;
        py = y;
        w = width;
        h = height;
    }
    /**
    *设置矩形类型
    *@param t   矩形类型
    */
    public void setType(int t){
        type = t;
    }
    /**
    *设置3D矩形类型
    *@param r   是否升起
    */
    public void set3DType(boolean r){
        raised =r;
    }
    /**
    *设置圆角矩形的圆角
    *@param xd  x方向圆角直径
    *@param yd  y方向圆角直径
    */
    public void setRound(int xd,int yd){
        ax = xd;
        ay = yd;
    }
    /**
    *@see PrintObject#print
    */
    public void print(Graphics gg){
        Graphics2D g = (Graphics2D)gg;
        g.setStroke(bs);
        switch (type){
            case REC3D:{
                g.draw3DRect(px, py, w, h, raised);
                break;
            }
            case RECNORMAL:{
                g.drawRect(px, py, w, h);
                break;
            }
            case RECROUND:{
                g.drawRoundRect(px, py, w, h, ax, ay);
                break;
            }
        }
    }
}

5、 打印内容的基类的设计

基类必须具有要有一个打印对象的容器,程序中使用了Vector对象。并且需要有将打印对象加入到容器中和取出的功能,具体设计如下:

package lilidb;
import java.util.*;
import java.awt.*;
public class PagePrint {
  /** 用来存储打印对象 **/
  Vector vc;
  public PagePrint() {
    vc = new Vector();
  }
  /**
  *将 PrintObject 对象放入 vc 中
  *@param po  PrintObject
  */
  public void putPrintO(PrintObject po){
    vc.add(po);
  }
  /**
  *取出PrintObject
  *@param i   在集合vc 中的序号
  */
  public PrintObject getPrintO(int i){
    return (PrintObject)vc.get(i);
  }
  /**
   * 遍历vc,执行每个PrintObject对象的print方面
   * @param g 将要打印的图形环境
   */
  public void print(Graphics g){
    int i = vc.size();
    Graphics2D g2d = (Graphics2D)g;
    for(int j=0;j<i;j++){
      getPrintO(j).print(g2d);
    }
  }
}

6、 实际打印类的设计

实际的打印类的设计,可根据实际需要而定,添加必要的功能,但必须封装Printable接口并继承PagePrint类,一般形式如下:

class PrintAll extends PagePrint implements Printable {
  public int print(Graphics g, PageFormat pf, int pageIndex) throws PrinterException {
    super.print(g);
    return Printable.PAGE_EXISTS;
  }
}

采用以上方法编写的代码均是可重用的,实际编写具体的打印程序时,只需要将打印的内容分解成相应的打印对象,然后将打印对象加入到容器中即可。既使用一个或多个PrintAll对象(每个PrintAll对象作为一页来处理),将分解的打印对象定义,设置相应的属性,然后使用PrintAll.putPrintO(PrintObject po)方法加入到容器中。这样编写打印程序就无需再考虑繁琐的逻辑了,只需分解对象,计算位置即可。是不是很爽呢?笔者在使用java开发一个金融项目时,就成功使用了上述技术,大大提高了工作效率。如需要更多的程序请和笔者联系,地址: zhangld@mail.hf.ah.cn



参考资料

java平台上的打印: http://java.sun.com/printing/

java网站的打印用例:
http://java.sun.com/docs/books/tutorial/2d/printing/example-1dot2/ShapesPrint.java
http://java.sun.com/docs/books/tutorial/2d/printing/example-1dot2/SimpleBook.java

developerworks上文枫的《java打印程序设计》:
http://www.ibm.com/developerworks/cn/java/l-javaprint/index.shtml



关于作者

 

张来东 java技术的爱好者,从jdk1.1开始,跟踪使用java语言开发软件(服务器端和客户端),在《网络世界》、《中国计算机报》、《计算机世界报》上发表了多篇java方面的技术文章。目前在中国人民银行六安市中心支行科技科工作。
联系地址:安徽省六安市人民路41号 中国人民银行六安市中心支行
邮编:237006
email: zhangld@mail.hf.ah.cn
zld@ah163.com

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值