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