用Java打造的图形化表格类库
杨恒贤 (yanghx@70345.com)
关键词: Java UML Together
本文通过Together建模设计一种与Web页中表格元素相近的图形化组建。主要用于图形表格的动态生成。本文用UML建立的类图关系,并用Java实现,全部类继承自定义的HTMLElement类,并且能很容易扩展。
1. 简介
本文讨论了怎么利用建模工具和Java打造一个复杂的类库。我们用Java与Together来实现一个图形化表格的类库,并且如何来使用这个类库生成多彩的图形化界面,并且支持JSP。
2. 要求功能描述
a) 我们要求这个类库实现Web页面上表格元素的功能,用于显示相应数据。所以每一个表格就是一个对象,所以我们定义表格类HTMLTable,要提供额外的功能我们只要从HTMLTable继承扩展就行了。
b) 可以方便的进行自定义设计,定义每一列的各种属性。我们把列也定义成一个类HTMLColumn。扩展列的属性只要从HTMLColumn扩展就行了。
c) 我们可以定义每一个单元个的属性,所以我们定义每一个单元个就是一个类。HTMLTableCell。扩展单元格的属性只要从HTMLTableCell扩展就行了。
d) 每一个Tanle多有几个单元块(例如上图的A,B)组成。我们将这种单元块定义为一种类HTMLTableSection。用于管理表格中的块。
e) 每一个单元块由一个合并了的单元个与一系列行组成,我们将合并了单元个定义成HTMLTableSectionCell,并且它与HTMLTableCell相近,所以我们在这2个类上导出一个共同基类HTMLBaseTableCell
f) 上面说到的行也是一种对象,所以我们将其定义为一种对象HTMLTableRow。
当你要定制其中某一种类的属性时,只要继承类重写其中的虚拟函数。以HTML开头的类实现了Web页中表格的功能。下面演示的以MV开头的就是继承来实现上面那种形式的表格。
3. 用UML工具进行类库设计
我们选用了Borland的建模工具Together。这个类图框架如下:
上面那幅图就是Together中画出的各类关系图。
l 为了使各类关系紧密连接起来,我们设计了一个公共父类HTMLElememt,提供一些共有的功能。提供属性如下
水平对齐属性m_nHAlign,表明元素里面的内容水平对其方式
竖直对其属性m_nVAlign,表明元素里面的内容竖直对其方式
元素父类组件m_parentTable,表明此元素的在哪一个元素上。
提供了相关的虚函数。
getWidth() 取得该对象的宽度。
l 在这里我们大量使用了Java中的ArrayList来管理对象的集合。在使用过程中由于全部是从HTMLElement继承,我们就使用了强制对象转化,从父类转化到子类(因为Java1.4还不支持泛型)。
l 我们为那种实现特定功能的函数尽量放在一个虚拟函数中,这样就可以使继承时用最少的代码实现定制功能。
具体的看提供的类库源代码。
4. 扩展
下面重点说一下我们怎么扩展这个类库,实现我们需要的功能。我们下面以实例来说明如何扩展。
最简单的就是如何定制某一个单元个的边框等属性。
单元格定制
我们继承单元格类HTMLTableCell
重载drawBorder()画出Cell的边框。
Class MyTableCell extends HTMLTableCell{
protected void drawBorder(java.awt.Graphics2D g, int left, int top, int width,
int height) {
Color prev=g.getColor();
g.setColor(Color.RED);
g.drawRect(left, top, width, height);
g.setColor(prev);
}
}
运行效果如下
当我们要更高级别的定制时,我们就需要重写
public void draw(Graphics2D g, Point pt),他就是提供了那个单元个的全部功能。这样你要怎么写就怎么写。
行的定制:
以实线分割:
public class MyRow extends HTMLTableRow{
public MyRow(){
}
protected void drawLine(Graphics2D g,int left,int top,int right){
g.drawLine(left,top,right,top);
}
}
运行效果
当然由于每一个类多有一个函数实现自己全部的图画过程draw(),所以当你想全部自己重画的时候就利用提供参数进行作画。
5. 使用
关于本类库的使用,遵循的是
Table是由一系列TableSection组成的,而TableSection是由一系列TableRow与一个TableSectionCell组成,每一个TableRow是由一些列TableCell组成。
当你想定制元素属性时,当定制有冲突时,其遵循的原则是:
TableCell优先级>TableRow优先级>TableSection优先级>Table优先级>TableColumn优先级.
下面演示一下怎么使用这些类:
Public class TestClass{
public static void main(String[] args) throws FileNotFoundException,
ImageFormatException, IOException {
TestFrame frame=new TestFrame();
frame.setSize(700,600);
frame.show();
BufferedImage image = (BufferedImage) frame.createImage(600,400);
Graphics2D g=(Graphics2D) image.getGraphics();//g就是要在这上面作画
MVTable table=new MVTable();//创建表格对象
table.addColumn(new HTMLTableColumn(30));
table.addColumn(new HTMLTableColumn(30));
table.addColumn(new HTMLTableColumn(150));
for(int i=0;i<5;i++){
table.addColumn(new HTMLTableColumn(60,i+2,1,new Color(i*25,i*10+125,255-i*50)));
}
//上面是定义表格的列的属性
HTMLTableSection sec=new HTMLTableSection();
//创建一个TableSection
HTMLSectionCell cell=new HTMLSectionCell(new Color(0x008080),"A");
sec.createSection(cell);
HTMLTableRow row=new MVTableRow(3.0,Color.CYAN);
HTMLTableCell c=new HTMLTableCell();
c.setCaption("1-1");
row.addCell(c);
c=new HTMLTableCell(Color.GRAY,"定制单元背景");
row.addCell(c);
for(int i=0;i<5;i++){
c=new HTMLTableCell();
row.addCell(c);
}
sec.addRow(row);//增加一个HTMLTableRow对象
row=new MVTableRow(3.5,Color.RED);
c=new HTMLTableCell(new Color(0x00ccff),"1-2");
row.addCell(c);
Font temp=new Font("宋体",Font.BOLD,14);
c=new HTMLTableCell(temp,null,"定制单元格字体");
row.addCell(c);
for(int i=0;i<5;i++){
c=new HTMLTableCell();
row.addCell(c);
}
sec.addRow(row);
table.addSection(sec);
//-----------------------
sec=new HTMLTableSection();
cell=new HTMLSectionCell(new Color(0x99ccff),"B");
sec.createSection(cell);
row=new MVTableRow(4.1,Color.BLUE);
c=new HTMLTableCell();
c.setCaption("2-1");
row.addCell(c);
c=new HTMLTableCell();
c.setCaption("定制行高");
row.addCell(c);
for(int i=0;i<5;i++){
c=new HTMLTableCell();
row.addCell(c);
}
row.setHeight(60);
sec.addRow(row);
row=new MVTableRow(5.1,Color.PINK);
c=new HTMLTableCell(Color.YELLOW,"2-2");
row.addCell(c);
c=new MyTableCell();
c.setCaption("重写drawBorder");
row.addCell(c);
for(int i=0;i<5;i++){
c=new HTMLTableCell();
row.addCell(c);
}
sec.addRow(row);
row=new MyRow();
c=new HTMLTableCell(Color.YELLOW,"2-3");
row.addCell(c);
c=new HTMLTableCell();
c.setCaption("重写行的drawLine");
row.addCell(c);
for(int i=0;i<5;i++){
c=new HTMLTableCell();
row.addCell(c);
}
sec.addRow(row);
row=new HTMLTableRow();
c=new HTMLTableCell(Color.YELLOW,"2-3");
row.addCell(c);
c=new HTMLTableCell();
c.setCaption("重写");
row.addCell(c);
for(int i=0;i<5;i++){
c=new HTMLTableCell();
row.addCell(c);
}
sec.addRow(row);
table.addSection(sec);
table.addInfo("继承定制单元格",3,2);
table.addInfo("行的也可被定制",5,1);
table.addInfo("表格也可以",6,1);
table.addInfo("大不了我不调用基类功能,完全重写 ",7,1);
table.draw(g);
//========================================================
OutputStream out=new FileOutputStream("C:\\1.jpg");
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
// encoder.setJPEGEncodeParam();
encoder.encode(image);
out.close();
}
}
6. 小结
这个类库构建过程中,我们用Borland的Together来构建相关的功能类图,并指明其关系。我们以关键数据与关键功能自我管理的原则来构建,这样的系统比较利于用继承的方法来进行功能续加。
小弟水平有限,如有不足请批评指正,谢谢。
类库下载地址:下载源代码