技术开发 频道

保留的图形对象API 简介

  类 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 的定义

1 public abstract class Drawable implements Cloneable
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

1 public class DrawableText extends Drawable {
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

1 public class DrawableLine extends Drawable
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

1 public class DrawableSprite extends Drawable
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的数组实现

1 public class DrawableSprite extends Drawable
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

1 public abstract class DrawableRectForm extends Drawable
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

1 public class DrawableBox extends DrawableRectForm
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
0
相关文章