// // another example of the Java AWT, showing use of Graphics and // Canvas classes. // see class definition for details. // import java.awt.* ; import java.awt.event.* ; import java.util.* ; // // a PolyDraw object is a CloseableFrame containing a PolyDrawPad // (see its definition), a ColorChooser (see its definition), // and a "clear" button. // class PolyDraw extends CloseableFrame { private PolyDrawPad pad ; PolyDraw() { super("PolyDraw") ; setLayout(new BorderLayout()) ; Panel controlP = new Panel() ; ColorChooser colorC = new ColorChooser() ; controlP.add(colorC) ; Button clearB = new Button("clear") ; controlP.add(clearB) ; pad = new PolyDrawPad(400, colorC) ; add(pad, "Center") ; add(controlP, "South") ; clearB.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { pad.clear() ; } } ) ; pack() ; show() ; } // ---- inner classes ------------------------------------------ // // a PolyDrawPad object is a Canvas on which we can draw // a collection of filled polygons. // to draw a polygon, the user must: // (1) click the left mouse button three or more times to // define points in the polygon, and // (2) click the right mouse button to "finish" the // polygon (connect the last point to the first point, // producing a closed polygon). the color for the // polygon is determined by the state of a ColorChooser // object (see its definition). // what appears on the screen are the (possibly overlapping) // polygons, drawn in the order in which they were // defined, and a Polyline representing a polygon-in-work, // including the points defined so far (with left-button // mouse clicks) and the current mouse position. // the object also provides a clear() method to reset to the // initial state (no polygons). // class PolyDrawPad extends Canvas implements MouseListener, MouseMotionListener { // off-screen image and its graphics context, used // to draw with double-buffering technique. private Image padImage ; private Graphics padGC ; // completed polygons -- elements of this Vector will // be ColoredPoly objects. private Vector polys ; // polygon "in work". private Polygon polyInWork ; // mouse position. // (-1, -1) means we haven't responded to a // mouse-motion event since we started drawing // the polygon in work. private int xpos, ypos ; // control object that provides selected color via // its chosenColor() method. private ColorChooser colorC ; // ---- constructor ------------------------------------ PolyDrawPad(int size, ColorChooser c) { super() ; colorC = c ; setSize(new Dimension(size, size)) ; setBackground(Color.white) ; polys = new Vector() ; polyInWork = new Polygon() ; xpos = -1 ; ypos = -1 ; addMouseListener(this) ; addMouseMotionListener(this) ; } // ---- other methods ---------------------------------- // responds to mouse-click events: // if left button, adds a point to the polygon in // work. // otherwise "finishes" the polygon (rejecting if // fewer than three points because such // polygons don't display). // requests repaint. public void mouseClicked(MouseEvent e) { if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0) { polyInWork.addPoint(e.getX(), e.getY()) ; } else { // add a polygon to our list. if (polyInWork.npoints >= 3) polys.addElement( new ColoredPoly( polyInWork, colorC.chosenColor())) ; // reset to draw a new one. polyInWork = new Polygon() ; xpos = -1 ; ypos = -1 ; } repaint() ; } // responds to mouse-motion events: // if we have a polygon in work, resets mouse // position and requests repaint. public void mouseMoved(MouseEvent e) { if (polyInWork.npoints > 0) { xpos = e.getX() ; ypos = e.getY() ; repaint() ; } } // ignore other MouseListener, MouseMotionListener // events. public void mousePressed(MouseEvent e) { } public void mouseDragged(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } // re-initializes -- resets to zero polygons and // requests repaint. private void clear() { polys = new Vector() ; polyInWork = new Polygon() ; xpos = -1 ; ypos = -1 ; repaint() ; } // updates display (triggered by repaint()). public void update(Graphics g) { paint(g) ; } // produces the desired display. public void paint(Graphics g) { // first time through, create an offscreen // image and get its graphics context. if (padImage == null) { padImage = createImage(getSize().width, getSize().height) ; padGC = padImage.getGraphics() ; } // produce the desired display on the // offscreen image's graphics context. padGC.clearRect(0, 0, getSize().width, getSize().height) ; drawCompleted(padGC) ; drawPartial(padGC) ; // draw onto the "real" graphics context. g.drawImage(padImage, 0, 0, null) ; } // draws "completed" polygons. private void drawCompleted(Graphics g) { for (int i = 0 ; i < polys.size() ; i++) { ColoredPoly p = (ColoredPoly) polys.elementAt(i) ; g.setColor(p.color) ; g.fillPolygon(p.poly) ; } } // draws the desired Polyline for the polygon-in-work // (if none, draw nothing). private void drawPartial(Graphics g) { if (polyInWork.npoints > 0) { // make a temporary Polygon object: // start with polygon in work. Polygon tempP = new Polygon( polyInWork.xpoints, polyInWork.ypoints, polyInWork.npoints) ; // if mouse position is valid, add it. if ((xpos >= 0) && (ypos >= 0)) tempP.addPoint(xpos, ypos) ; g.setColor(colorC.chosenColor()) ; g.drawPolyline(tempP.xpoints, tempP.ypoints, tempP.npoints) ; } } } // a ColoredPolygon object represents one of the polygons to // be drawn, i.e., combines a Polygon and a Color. class ColoredPoly { Polygon poly ; Color color ; ColoredPoly(Polygon p, Color c) { poly = p ; color = c ; } } // ---- main --------------------------------------------------- // // no command-line arguments. // public static void main(String[] args) { PolyDraw r = new PolyDraw() ; } } // // a ColorChooser object is a Choice whose items represent the // predefined colors of the Color class. it also provides // a chosenColor() method to return the selected color. // class ColorChooser extends Choice { private static final ColorChoice[] choices = { new ColorChoice(Color.black, "black"), new ColorChoice(Color.blue, "blue"), new ColorChoice(Color.cyan, "cyan"), new ColorChoice(Color.darkGray, "darkGray"), new ColorChoice(Color.green, "green"), new ColorChoice(Color.lightGray, "lightGray"), new ColorChoice(Color.magenta, "magenta"), new ColorChoice(Color.orange, "orange"), new ColorChoice(Color.pink, "pink"), new ColorChoice(Color.red, "red"), new ColorChoice(Color.white, "white"), new ColorChoice(Color.yellow, "yellow") } ; ColorChooser() { super() ; for (int i = 0 ; i < choices.length ; i++) add(choices[i].name) ; } Color chosenColor() { return choices[getSelectedIndex()].color ; } // ---- inner classes ------------------------------------------ // a ColorChoice object pairs one of the predefined colors of // the Color class with its (text) name. static class ColorChoice { Color color ; String name ; ColorChoice(Color c, String n) { color = c ; name = n ; } } }