Creating Object-Oriented Graphics

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.


  1. To draw an object on the screen, you create an instance of the object and register it with a canvas object
  2. Objects have settable properties, such as location, size, color, visibility
  3. Objects have draw methods that handle the graphics context and render the object
  4. Objects can express an interest in handling various types of events--the event handlers for these objects will be automatically notified when the event occurs
  5. You can use container objects to organize related groups of objects
  6. You can associate layout managers with container objects
  7. You can associate a display manager with a canvas object

Inheritance Hierarchy

  AbstractShape implements Shape (these are drawable shapes):
       EllipseShape, ImageShape, RectangleShape, TextShape

  ContainerShape: Holds groups of Shape objects
  CanvasShape: The object that provides a surface on which Shapes are drawn

  Shape Interface: 
    addInteractor/removeInteractor: adds an event handler to this object
    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
	    // width and height may require a special calculation
            g.fillRect(left, top, getWidth(), getHeight());

          FontMetrics fm = g.getFontMetrics();
          g.drawString(text, left, top + fm.getAscent());

  DisplayManager interface
	display(Graphics2D g): draws all the shapes in the canvas
        damage(Rectangle r): indicates what portion of the canvas has
		changed and needs to be redrawn
	setCanvas(CanvasShape): indicates which canvas this display manager will
	   be managing

Shape Classes


AbstractShape is the abstract base class for all silhouette shapes
    Subclasses: BoxShape, LineShape
    Defined properties
      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


    Subclasses: EllipseShape, ImageShape, RectangleShape,
    Defined properties
      left, top
      width, height


    Subclasses: ArrowLineShape
    Defined properties
      x1, y1
      x2, y2


A ContainerShape serves two purposes:

  1. group a loosely related set of objects for layout purposes
  2. 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)
      revalidate: asks the layout manager to re-layout the objects in
	the container

       public void draw(Graphics2D g) {
         for each shape in getShapes() {


   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
         void setDisplayManager(DisplayManager d) {
	    displayMgr = d;
         paintComponent(Graphics g) {

Example Display Manager (pseudo-code)

The following pseudo-code shows how a sample display manager might be implemented:

     class TotalRedraw implements DisplayManager {
       CanvasShape canvas;

       public void setCanvas(CanvasShape c) {
	  canvas = c;
       public void damage(Rectangle r) {
	 // do nothing since we are doing a total redraw

       public void Display(Graphics2D g) {
         for each shape in canvas.getShapes() {