类 Drawable 是可绘制对象的一个抽象模型,用于提供这些对象的公共定义和行为。每个可绘制对象的类型由 Drawable 的非抽象子类定义。这些子类定义了受支持的 RGO。我准备了一个可绘制对象类型的具有代表性的样本,这些对象可能使用 java.awt.Graphics 服务。通过建立 Drawable 或者 DrawableRectForm 的子类可以添加其它保留对象类型。
所有 Drawable 实例共享一些公共特征:
可见性:每个 Drawable 实例可以标记为 visible(可见)或 invisible(不可见)。不绘制不可见对象。实例的可见性可以在任何时候更改。
缩放:每个 Drawable 实例都有一个缩放因子(即,缩放比:M:N)。缺省值为 1:1 的比例。当 M 值比 N 值大时放大对象。相应地,M 值小于 N 值时缩小对象。这个比例通过类 Scale 实现。请注意,使用整数比例而不是浮点进行缩放,是因为整数比例需要较少的运行时计算(即,浮点和/或双精度与整数格式之间的转换)。
颜色:每个 Drawable 实例都有一个 java.awt.Color 值。通常以这种颜色绘制实例。子类可能支持多颜色对象。在这种情况下,颜色值可以被忽略或者作缺省值或者底色。
请参阅下面的清单 1,查看类 Drawable 的定义。 Drawable 是抽象的,因为它本身没有绘图功能。它是可克隆的,因为这样很容易在不知道特殊对象子类名称的情况下复制 Drawable 对象。 draw() 和 DrawWorker() 方法实际上导致显示 Drawable 对象。 draw() 方法用来处理可见与不可见对象的表示。方法 drawWorker() 是一个抽象方法,必须在 Drawable 的所有非抽象子类中定义。它负责描绘对象。通常,它使用 DrawingContext 类的服务方法来完成。
当使用自存储持久性时, loadFrom() 和 storeOn() 方法为 PersistentDrawable 对象提供持久性支持。每个添加实例变量的 PersistentDrawable 子类必须覆盖这些方法。由于文章篇幅有限,我不在所有的子类定义中显示这些方法,但所有这些方法都与下面的类 DrawableSprite 显示和描述的方法相似。
清单 1. 类 Drawable 的定义
2 {
3 protected Color _color; // object color
4 protected boolean _visible; // object is shown
5 protected Scale _scaler; // scale by this
6 protected Drawable(Color color, boolean visible, Scale scale) {
7 _color = new Color(color.getRGB());
8 _visible = visible;
9 _scaler = (Scale)scale.clone();
10 }
11 // draw myself
12 public final void draw(DrawingContext context) {
13 if(_visible) drawWorker(context);
14 }
15 abstract protected void drawWorker(DrawingContext context);
16 // save myself persistently
17 public void storeOn(DataOutputStream dos) throws IOException {
18 dos.writeByte(_color.getRed());
19 dos.writeByte(_color.getGreen());
20 dos.writeByte(_color.getBlue());
21 dos.writeInt(_scaler.multBy); dos.writeInt(_scaler.divBy);
22 dos.writeBoolean(_visible);
23 }
24 // reload myself from persistent storage
25 public void loadFrom(DataInputStream dis) throws IOException {
26 _color = new Color(s.readByte(), is.readByte(), dis.readByte());
27 _scaler = new Scale(is.readInt(), dis.readInt());
28 _visible = dis.readBoolean();
29 }
30 }
类 Drawable 的子类
本节中总结的 Drawable 的可描绘子类将要提供如何编码可绘制对象的示例。它们不一定是绘图应用程序需要的所有类型对象的代表。可以在包含的源文件中找到下面描述的所有子类。
类 DrawableText
类 DrawableText 定义一行水平文本。 DrawableText 对象是 java.awt.Graphics.drawString 函数的直接表示。可以设置文本的开始位置、前景色和字体大小。实际所用的字体大小是为活动 Java 字体定义的最接近字体大小。如果所期望的字体太小(2 点或者更小),那么将无法绘制文本。
DrawableText 从 Drawable 继承而来。它定义 drawWorker(...) 方法。这个方法,象所有其它 Drawable 子类 drawWorker() 方法一样,只是调用类 DrawingContext 参数的服务方法。
清单 2. 类 DrawableText
2 protected Point _start; // coordinates
3 protected String _text;
4 protected int _fontSize; // display size
5 // draw myself
6 public void drawWorker(DrawingContext context) {
7 context.drawText(_scaler.scale(_start), _text, _scaler.scale(_fontSize), _color);
8 }
9 }
10
类 DrawableLine
类 DrawableLine 定义了一条直线。 DrawableLine 对象是 java.awt.Graphics.drawLine 函数的直接表示。可以设置直线的开始和结束位置以及颜色。如上所述, DrawableLine 的 drawWorker() 方法调用类 DrawingContext 参数的服务方法。这适用于 Drawable 的所有子类的 drawWorker() 方法。清单 3 是类 DrawableLine 的定义。
清单 3. 类 DrawableLine
2 {
3 protected Point _start, _end; // coordinates
4 // draw myself
5 public void drawWorker(DrawingContext context) {
6 context.drawLine(_scaler.scale(_start), _scaler.scale(_end), _color);
7 }
8 }
9
类 DrawableSprite
类 DrawableSprite 定义了一个 36 条直线的集合,这 36 条直线从一个公共中心点向外延伸,相邻两线之间的夹角为 10 度。每条直线有随意选择的不同颜色。因此忽略了继承的颜色值。可以设置中心点和直线的长度。 DrawableSprite 对象是由一些 java.awt.Graphics.drawLine 图元函数构成的。它显示 Drawable 子类不受 java.awt.Graphics 服务直接表示的限制。清单 4 是类 DrawableSprite 的定义。
清单 4. 类 DrawableSprite
2 {
3 protected Point _center; // coordinates
4 protected int _length; // line length
5 // draw myself
6 public void drawWorker(DrawingContext context) {
7 context.drawSprite(_scaler.scale(_center), _scaler.scale(_length));
8 }
9 }
10
DrawableSprite 的另一个实现是使用 DrawableLine 实例的集合。在这种情况下,不需要 DrawingContext.drawSprite() 方法。清单 5 显示了修改过的类 DrawableSprite 定义。这里,直线包含在实例中而不是由 DisplayContext 服务方法绘制。因为在对象中有多条直线,每条直线都必须由函数性方法处理。
清单 5. 类 DrawableSprite的数组实现
2 {
3 private int numlines = 36;
4 protected DrawableLine[] _lines = new DrawableLine[numlines];
5 public DrawableSprite(Point center, int length, boolean visible, Scale scale) {
6 super(Color.white, visible, scale);
7 double step;
8 int i;
9 PositiveRandom rgb = new PositiveRandom(256);
10 // make radial lines every 2Pi/numlines radians;
11 // each line is a different color
12 for(i = 0, step = 0 * Math.PI;
13 i < numlines;
14 i++, step += Math.PI / numlines) {
15 double sin = Math.sin(step), cos = Math.cos(step);
16 DrawableLine line = new DrawableLine(
17 Point(center.x + (int)((length / 10) * cos),
18 center.y - (int)((length / 10) * sin)),
19 Point(center.x + (int)( length * cos),
20 center.y - (int)( length * sin)),
21 new Color(rgb.next(), rgb.next(), rgb.next()), true, _scaler);
22 _lines[i] = line;
23 }
24 }
25 public void setScale(Scale scale) {
26 super.setScale(scale);
27 // scale each line
28 for(int i = 0; i < numlines; i++) {
29 _lines[i].setScale(scale);
30 }
31 }
32 // draw myself
33 public void drawWorker(DrawingContext context) {
34 // draw each line
35 for(i = 0; i < numlines; i++) {
36 _lines[i].draw(context);
37 }
38 }
39 // save myself
40 public void storeOn(DataOutputStream dos) throws IOException {
41 super.storeOn(dos);
42 // save each line
43 dos.writeInt(numlines);
44 for(int i = 0; i < numlines; i++) {
45 _lines[i].storeOn(dos);
46 }
47 }
48 // reload myself
49 public void loadFrom(DataInputStream dis) throws IOException {
50 super.loadFrom(dis);
51 // load each line
52 numlines = dis.readInt(numlines);
53 _lines = new DrawableLine[numlines];
54 for(int i = 0, i < numlines; i++) {
55 _lines[i] = new DrawableLine();
56 _line[i].loadFrom(dis);
57 }
58 }
59 }
60
loadFrom(...) 和 storeTo(...) 方法将从 Drawable 继承来的方法扩展为分别装入和保存该类引入的附加字段。
另一种实现是使用 DrawableSequencer 而不是数组来保留这些直线。这将不需要使用 for 循环来迭代每条直线。这个解决方案将需要 DrawableSequencer 从 Drawable 继承。
类 DrawableRectForm
类 DrawableRectForm 为可以由边界矩形框描述的可绘制对象定义了抽象模型。示例有实心和空心圆、椭圆以及矩形。可以设置对象的边角位置、宽度、高度和颜色。
清单 6 显示了类 DrawableRectForm 的定义。由于 DrawableRectForm 是抽象的,所以不需要为它实现 drawWorker(...) 方法。
清单 6. 类 DrawableRectForm
2 {
3 protected Rectangle _area; // coordinates & size
4 }
5
类 DrawableBox 和类 DrawableOval
类 DrawableBox 和类 DrawableOval 分别定义了实心矩形和圆形(或者椭圆形)对象。 DrawableBox 对象是 java.awt.Graphics.fillRect 函数的直接表示; DrawableOval 对象是 java.awt.Graphics.fillOval 函数的直接表示。可以设置对象的边角位置、宽度、高度和颜色。
清单 7 显示了类 DrawableBox 和类 DrawableOval 的定义。由于这两个类都从 DrawableRectForm 继承而来并且没有添加新的实例变量,因此它们不需要定义 loadFrom(...) 和 storeTo(...) 方法。
清单 7. 类 DrawableBox 和类DrawableOval
2 {
3 // draw myself
4 public void drawWorker(DrawingContext context) {
5 context.drawBox(_scaler.scale(_area), _color);
6 }
7 }
8 public class DrawableOval extends DrawableRectForm
9 {
10 // draw myself
11 public void drawWorker(DrawingContext context) {
12 context.drawOval(_scaler.scale(_area), _color);
13 }
14 }
15