Creating Object-Oriented Graphics
It is best to read these notes after the object modeling lecture. They
might not make sense if you read them beforehand.
These notes provide a nice design example for creating a simple hierarchy
of graphical objects. You will flesh out this design in a homework assignment.
Principles
- To draw an object on the screen, you create an instance of the object and
register it with a canvas object
- Objects have settable properties, such as location, size, color, visibility
- Objects have draw methods that handle the graphics context and render
the object
- You can use container objects to organize related groups of objects
- You can associate layout managers with container objects
- You can associate a display manager with a canvas object
Inheritance Hierarchy
AbstractShape implements Shape (these are drawable shapes):
BoxShape
EllipseShape, ImageShape, RectangleShape, TextShape
LineShape
ArrowShape
ContainerShape: Holds groups of Shape objects
CanvasShape: The object that provides a surface on which Shapes are drawn
Shape Interface:
draw(Graphics2D): renders the object using the given Graphics2D context
contains(x,y): indicates whether or not the object contains the given
(x,y) point
getBounds: returns the bounding box for this object
Example draw routine for a TextShape:
public void draw(Graphics2D g) {
if (visible) {
if (filled) { // fill a box behind the TextShape
g.setColor(fillColor);
// width and height may require a special calculation
g.fillRect(left, top, getWidth(), getHeight());
}
g.setColor(lineColor);
g.setFont(font);
FontMetrics fm = g.getFontMetrics();
g.drawString(text, left, top + fm.getAscent());
}
Shape Classes
AbstractShape
AbstractShape is the abstract base class for all silhouette shapes
Subclasses: BoxShape, LineShape
Defined properties
visible
parent
lineColor
fillColor
Filled: whether or not the object is filled or transparent
There is no location or size attributes because rectangular objects and
line objects represent this information differently
Line objects might not have a fill color but arrowlines might, so it
is okay to have the fillColor property defined for line objects
BoxShape
BoxShape
Subclasses: EllipseShape, ImageShape, RectangleShape,
TextShape
Defined properties
left, top
width, height
LineShape
LineShape
Subclasses: ArrowLineShape
Defined properties
x1, y1
x2, y2
ContainerShape
A ContainerShape serves two purposes:
- group a loosely related set of objects for layout purposes
- group a tightly related set of objects that should be treated as
a single entity (e.g., a labeled rectangle)
ContainerShape: container object--uses a BoxShape for composition. Does not
want to provide an interface that allows the setting of line or fill
properties, so it cannot be a subclass of BoxShape
Defined properties
shapes: list of shapes for this container
layoutManager: the layout manager for this container
New methods
add: adds an object to the container
bringToFront/sendToBack: brings an object to the front of the container
or sends it to the back, so that it is covered by the other objects
in the container
getShapes: returns a list of the shapes in this container, ordered from
back to front (i.e., the first items in the list should be in back and
the last items should be in front)
get/setLayoutManager
revalidate: asks the layout manager to re-layout the objects in
the container
public void draw(Graphics2D g) {
for each shape in getShapes() {
shape.draw(g);
}
}
CanvasShape
CanvasShape: creates a JPanel that can be added to a Java container
Superclass: JPanel
Uses a ContainerShape for composition, since a CanvasShape is essentially
a container object. It will delegate the add, getShapes, and
BringToFront/SendToBack methods to the container while ignoring the
layout methods, since it will be communicating with a display manager
instead
Methods
paintComponent(Graphics g) {
super.paintComponent(g);
for each shape in getShapes() {
shape.draw(g);
}
}