Canvas.java (7181B)
1 import javax.swing.*; 2 import java.awt.*; 3 import java.util.List; 4 import java.util.*; 5 6 /** 7 * Canvas is a class to allow for simple graphical drawing on a canvas. 8 * This is a modification of the general purpose Canvas, specially made for 9 * the BlueJ "shapes" example. 10 * 11 * @author: Bruce Quig 12 * @author: Michael Kolling (mik) 13 * 14 * @version: 1.6 (shapes) 15 */ 16 public class Canvas 17 { 18 // Note: The implementation of this class (specifically the handling of 19 // shape identity and colors) is slightly more complex than necessary. This 20 // is done on purpose to keep the interface and instance fields of the 21 // shape objects in this project clean and simple for educational purposes. 22 23 private static Canvas canvasSingleton; 24 25 /** 26 * Factory method to get the canvas singleton object. 27 */ 28 public static Canvas getCanvas() 29 { 30 if(canvasSingleton == null) { 31 canvasSingleton = new Canvas("BlueJ Shapes Demo", 300, 300, 32 Color.white); 33 } 34 canvasSingleton.setVisible(true); 35 return canvasSingleton; 36 } 37 38 // ----- instance part ----- 39 40 private JFrame frame; 41 private CanvasPane canvas; 42 private Graphics2D graphic; 43 private Color backgroundColour; 44 private Image canvasImage; 45 private List<Object> objects; 46 private HashMap<Object,Object> shapes; 47 48 /** 49 * Create a Canvas. 50 * @param title title to appear in Canvas Frame 51 * @param width the desired width for the canvas 52 * @param height the desired height for the canvas 53 * @param bgClour the desired background colour of the canvas 54 */ 55 private Canvas(String title, int width, int height, Color bgColour) 56 { 57 frame = new JFrame(); 58 canvas = new CanvasPane(); 59 frame.setContentPane(canvas); 60 frame.setTitle(title); 61 canvas.setPreferredSize(new Dimension(width, height)); 62 backgroundColour = bgColour; 63 frame.pack(); 64 frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 65 objects = new ArrayList<Object>(); 66 shapes = new HashMap<Object,Object> (); 67 } 68 69 /** 70 * Set the canvas visibility and brings canvas to the front of screen 71 * when made visible. This method can also be used to bring an already 72 * visible canvas to the front of other windows. 73 * @param visible boolean value representing the desired visibility of 74 * the canvas (true or false) 75 */ 76 public void setVisible(boolean visible) 77 { 78 if(graphic == null) { 79 // first time: instantiate the offscreen image and fill it with 80 // the background colour 81 Dimension size = canvas.getSize(); 82 canvasImage = canvas.createImage(size.width, size.height); 83 graphic = (Graphics2D)canvasImage.getGraphics(); 84 graphic.setColor(backgroundColour); 85 graphic.fillRect(0, 0, size.width, size.height); 86 graphic.setColor(Color.black); 87 } 88 frame.setVisible(visible); 89 } 90 91 /** 92 * Draw a given shape onto the canvas. 93 * @param referenceObject an object to define identity for this shape 94 * @param color the color of the shape 95 * @param shape the shape object to be drawn on the canvas 96 */ 97 // Note: this is a slightly backwards way of maintaining the shape 98 // objects. It is carefully designed to keep the visible shape interfaces 99 // in this project clean and simple for educational purposes. 100 public void draw(Object referenceObject, String color, Shape shape) 101 { 102 objects.remove(referenceObject); // just in case it was already there 103 objects.add(referenceObject); // add at the end 104 shapes.put(referenceObject, new ShapeDescription(shape, color)); 105 redraw(); 106 } 107 108 /** 109 * Erase a given shape's from the screen. 110 * @param referenceObject the shape object to be erased 111 */ 112 public void erase(Object referenceObject) 113 { 114 objects.remove(referenceObject); // just in case it was already there 115 shapes.remove(referenceObject); 116 redraw(); 117 } 118 119 /** 120 * Set the foreground colour of the Canvas. 121 * @param newColour the new colour for the foreground of the Canvas 122 */ 123 public void setForegroundColor(String colorString) 124 { 125 if(colorString.equals("red")) 126 graphic.setColor(Color.red); 127 else if(colorString.equals("black")) 128 graphic.setColor(Color.black); 129 else if(colorString.equals("blue")) 130 graphic.setColor(Color.blue); 131 else if(colorString.equals("yellow")) 132 graphic.setColor(Color.yellow); 133 else if(colorString.equals("green")) 134 graphic.setColor(Color.green); 135 else if(colorString.equals("magenta")) 136 graphic.setColor(Color.magenta); 137 else if(colorString.equals("white")) 138 graphic.setColor(Color.white); 139 else 140 graphic.setColor(Color.black); 141 } 142 143 /** 144 * Wait for a specified number of milliseconds before finishing. 145 * This provides an easy way to specify a small delay which can be 146 * used when producing animations. 147 * @param milliseconds the number 148 */ 149 public void wait(int milliseconds) 150 { 151 try 152 { 153 Thread.sleep(milliseconds); 154 } 155 catch (Exception e) 156 { 157 // ignoring exception at the moment 158 } 159 } 160 161 /** 162 * Redraw ell shapes currently on the Canvas. 163 */ 164 private void redraw() 165 { 166 erase(); 167 for(Iterator i=objects.iterator(); i.hasNext(); ) { 168 ((ShapeDescription)shapes.get(i.next())).draw(graphic); 169 } 170 canvas.repaint(); 171 } 172 173 /** 174 * Get the width 175 */ 176 public int getWidth(){ 177 return canvas.getWidth(); 178 } 179 180 /** 181 * Get the height 182 */ 183 public int getHeight(){ 184 return canvas.getHeight(); 185 } 186 187 /** 188 * Erase the whole canvas. (Does not repaint.) 189 */ 190 private void erase() 191 { 192 Color original = graphic.getColor(); 193 graphic.setColor(backgroundColour); 194 Dimension size = canvas.getSize(); 195 graphic.fill(new Rectangle(0, 0, size.width, size.height)); 196 graphic.setColor(original); 197 } 198 199 200 /************************************************************************ 201 * Inner class CanvasPane - the actual canvas component contained in the 202 * Canvas frame. This is essentially a JPanel with added capability to 203 * refresh the image drawn on it. 204 */ 205 private class CanvasPane extends JPanel 206 { 207 public void paint(Graphics g) 208 { 209 g.drawImage(canvasImage, 0, 0, null); 210 } 211 } 212 213 /************************************************************************ 214 * Inner class CanvasPane - the actual canvas component contained in the 215 * Canvas frame. This is essentially a JPanel with added capability to 216 * refresh the image drawn on it. 217 */ 218 private class ShapeDescription 219 { 220 private Shape shape; 221 private String colorString; 222 223 public ShapeDescription(Shape shape, String color) 224 { 225 this.shape = shape; 226 colorString = color; 227 } 228 229 public void draw(Graphics2D graphic) 230 { 231 setForegroundColor(colorString); 232 graphic.fill(shape); 233 } 234 } 235 236 }