控制台程序。
在Sketcher中创建形状时,并不知道应该以什么顺序创建不同类型的形状,这完全取决于使用Sketcher程序生成草图的人。因此需要绘制形状,对它们执行其他操作而不必知道图形是什么。当然,多态性在这里是有帮助的。
最简单的方法可能是为Sketcher形状类定义通用的基类,并在每个形状类中包含一个成员来存储某种java.awt.geom形状对象,接着把对形状类对象的引用存储为基类类型以获得多态行为。
1、通用基类:
1 import java.awt.*; 2 import java.io.Serializable; 3 import static Constants.SketcherConstants.*; 4 import java.awt.geom.*; 5 6 public abstract class Element implements Serializable{ 7 8 public Element(Point position, Color color) { 9 this.position = new Point(position); 10 this.color = color; 11 } 12 13 protected Element(Color color) { 14 this.color = color; 15 } 16 17 // Returns the color of the element 18 public Color getColor() { 19 return color; 20 } 21 22 // Returns the position of the element 23 public Point getPosition() { 24 return position; 25 } 26 27 // Returns the bounding rectangle enclosing an element boundary 28 public java.awt.Rectangle getBounds() { 29 return bounds; 30 } 31 32 // Create a new element 33 public static Element createElement(int type, Color color, Point start, Point end) { 34 switch(type) { 35 case LINE: 36 return new Element.Line(start, end, color); 37 case RECTANGLE: 38 return new Rectangle(start, end, color); 39 case CIRCLE: 40 return new Circle(start, end, color); 41 case CURVE: 42 return new Curve(start, end, color); 43 default: 44 assert false; // We should never get to here 45 } 46 return null; 47 } 48 49 // Nested class defining a line 50 public static class Line extends Element { 51 public Line(Point start, Point end, Color color) { 52 super(start, color); 53 line = new Line2D.Double(origin.x, origin.y, end.x - position.x, end.y - position.y); 54 bounds = new java.awt.Rectangle( 55 Math.min(start.x ,end.x), Math.min(start.y, end.y), 56 Math.abs(start.x - end.x)+1, Math.abs(start.y - end.y)+1); 57 } 58 59 // Change the end point for the line 60 public void modify(Point start, Point last) { 61 line.x2 = last.x - position.x; 62 line.y2 = last.y - position.y; 63 bounds = new java.awt.Rectangle( 64 Math.min(start.x ,last.x), Math.min(start.y, last.y), 65 Math.abs(start.x - last.x)+1, Math.abs(start.y - last.y)+1); 66 } 67 68 // Display the line 69 public void draw(Graphics2D g2D) { 70 g2D.setPaint(color); // Set the line color 71 g2D.translate(position.x, position.y); // Move context origin 72 g2D.draw(line); // Draw the line 73 g2D.translate(-position.x, -position.y); // Move context origin back 74 } 75 private Line2D.Double line; 76 private final static long serialVersionUID = 1001L; 77 } 78 79 // Nested class defining a rectangle 80 public static class Rectangle extends Element { 81 public Rectangle(Point start, Point end, Color color) { 82 super(new Point(Math.min(start.x, end.x), Math.min(start.y, end.y)), color); 83 rectangle = new Rectangle2D.Double( 84 origin.x, origin.y, // Top-left corner 85 Math.abs(start.x - end.x), Math.abs(start.y - end.y)); // Width & height 86 bounds = new java.awt.Rectangle( 87 Math.min(start.x ,end.x), Math.min(start.y, end.y), 88 Math.abs(start.x - end.x)+1, Math.abs(start.y - end.y)+1); 89 } 90 91 // Display the rectangle 92 public void draw(Graphics2D g2D) { 93 g2D.setPaint(color); // Set the rectangle color 94 g2D.translate(position.x, position.y); // Move context origin 95 g2D.draw(rectangle); // Draw the rectangle 96 g2D.translate(-position.x, -position.y); // Move context origin back 97 } 98 99 // Method to redefine the rectangle 100 public void modify(Point start, Point last) { 101 bounds.x = position.x = Math.min(start.x, last.x); 102 bounds.y = position.y = Math.min(start.y, last.y); 103 rectangle.width = Math.abs(start.x - last.x); 104 rectangle.height = Math.abs(start.y - last.y); 105 bounds.width = (int)rectangle.width +1; 106 bounds.height = (int)rectangle.height + 1; 107 } 108 109 private Rectangle2D.Double rectangle; 110 private final static long serialVersionUID = 1001L; 111 } 112 113 // Nested class defining a circle 114 public static class Circle extends Element { 115 public Circle(Point center, Point circum, Color color) { 116 super(color); 117 118 // Radius is distance from center to circumference 119 double radius = center.distance(circum); 120 position = new Point(center.x - (int)radius, center.y - (int)radius); 121 circle = new Ellipse2D.Double(origin.x, origin.y, 2.*radius, 2.*radius); 122 bounds = new java.awt.Rectangle(position.x, position.y, 123 1 + (int)circle.width, 1+(int)circle.height); 124 } 125 126 // Display the circle 127 public void draw(Graphics2D g2D) { 128 g2D.setPaint(color); // Set the circle color 129 g2D.translate(position.x, position.y); // Move context origin 130 g2D.draw(circle); // Draw the circle 131 g2D.translate(-position.x, -position.y); // Move context origin back 132 } 133 134 // Recreate this circle 135 public void modify(Point center, Point circum) { 136 double radius = center.distance(circum); 137 circle.width = circle.height = 2*radius; 138 position.x = center.x - (int)radius; 139 position.y = center.y - (int)radius; 140 bounds = new java.awt.Rectangle(position.x, position.y, 141 1 + (int)circle.width, 1+(int)circle.height); 142 } 143 144 private Ellipse2D.Double circle; 145 private final static long serialVersionUID = 1001L; 146 } 147 148 // Nested class defining a curve 149 public static class Curve extends Element { 150 public Curve(Point start, Point next, Color color) { 151 super(start, color); 152 curve = new GeneralPath(); 153 curve.moveTo(origin.x, origin.y); // Set current position as origin 154 curve.lineTo(next.x - position.x, next.y - position.y); // Add segment 155 bounds = new java.awt.Rectangle( 156 Math.min(start.x ,next.x), Math.min(start.y, next.y), 157 Math.abs(next.x - start.x)+1, Math.abs(next.y - start.y)+1); 158 } 159 160 // Add another segment 161 public void modify(Point start, Point next) { 162 curve.lineTo(next.x - position.x, next.y - position.y); // Add segment 163 bounds.add(new java.awt.Rectangle(next.x,next.y, 1, 1)); // Extend bounds 164 } 165 166 167 // Display the curve 168 public void draw(Graphics2D g2D) { 169 g2D.setPaint(color); // Set the curve color 170 g2D.translate(position.x, position.y); // Move context origin 171 g2D.draw(curve); // Draw the curve 172 g2D.translate(-position.x, -position.y); // Move context origin back 173 } 174 175 private GeneralPath curve; 176 private final static long serialVersionUID = 1001L; 177 } 178 179 // Abstract Element class methods 180 public abstract void draw(Graphics2D g2D); 181 public abstract void modify(Point start, Point last); 182 183 // Element class fields 184 protected Point position; // Position of a shape 185 protected Color color; // Color of a shape 186 protected java.awt.Rectangle bounds; // Bounding rectangle 187 protected static final Point origin = new Point(); // Origin for elements 188 private final static long serialVersionUID = 1001L; 189 }
2、实现了链表和Iterable<Element>接口的模型:
1 import java.io.Serializable; 2 import java.util.*; 3 4 public class SketcherModel extends Observable implements Serializable, Iterable<Element> { 5 6 //Remove an element from the sketch 7 public boolean remove(Element element) { 8 boolean removed = elements.remove(element); 9 if(removed) { 10 setChanged(); 11 notifyObservers(element.getBounds()); 12 } 13 return removed; 14 } 15 16 //Add an element to the sketch 17 public void add(Element element) { 18 elements.add(element); 19 setChanged(); 20 notifyObservers(element.getBounds()); 21 } 22 23 // Get iterator for sketch elements 24 public Iterator<Element> iterator() { 25 return elements.iterator(); 26 } 27 28 29 protected LinkedList<Element> elements = new LinkedList<>(); 30 private final static long serialVersionUID = 1001L; 31 }
3、视图:
1 import javax.swing.JComponent; 2 import java.util.*; 3 import java.awt.*; 4 import java.awt.event.MouseEvent; 5 import javax.swing.event.MouseInputAdapter; 6 7 @SuppressWarnings("serial") 8 public class SketcherView extends JComponent implements Observer { 9 public SketcherView(Sketcher theApp) { 10 this.theApp = theApp; 11 MouseHandler handler = new MouseHandler(); // create the mouse listener 12 addMouseListener(handler); // Listen for button events 13 addMouseMotionListener(handler); // Listen for motion events 14 } 15 16 // Method called by Observable object when it changes 17 public void update(Observable o, Object rectangle) { 18 if(rectangle != null) { 19 repaint((java.awt.Rectangle)rectangle); 20 } else { 21 repaint(); 22 } 23 } 24 25 // Method to draw on the view 26 @Override 27 public void paint(Graphics g) { 28 Graphics2D g2D = (Graphics2D)g; // Get a 2D device context 29 for(Element element: theApp.getModel()) { // For each element in the model 30 element.draw(g2D); // ...draw the element 31 } 32 } 33 34 class MouseHandler extends MouseInputAdapter { 35 @Override 36 public void mousePressed(MouseEvent e) { 37 start = e.getPoint(); // Save the cursor position in start 38 buttonState = e.getButton(); // Record which button was pressed 39 if(buttonState == MouseEvent.BUTTON1) { 40 g2D = (Graphics2D)getGraphics(); // Get graphics context 41 g2D.setXORMode(getBackground()); // Set XOR mode 42 } 43 } 44 45 @Override 46 public void mouseDragged(MouseEvent e) { 47 last = e.getPoint(); // Save cursor position 48 49 if(buttonState == MouseEvent.BUTTON1) { 50 if(tempElement == null) { // Is there an element? 51 tempElement = Element.createElement( // No, so create one 52 theApp.getWindow().getElementType(), 53 theApp.getWindow().getElementColor(), 54 start, last); 55 } else { 56 tempElement.draw(g2D); // Yes draw to erase it 57 tempElement.modify(start, last); // Now modify it 58 } 59 tempElement.draw(g2D); // and draw it 60 } 61 } 62 63 @Override 64 public void mouseReleased(MouseEvent e) { 65 if(e.getButton() == MouseEvent.BUTTON1) { 66 buttonState = MouseEvent.NOBUTTON; // Reset the button state 67 68 if(tempElement != null) { // If there is an element... 69 theApp.getModel().add(tempElement); // ...add it to the model... 70 tempElement = null; // ...and reset the field 71 } 72 if(g2D != null) { // If there's a graphics context 73 g2D.dispose(); // ...release the resource... 74 g2D = null; // ...and reset field to null 75 } 76 start = last = null; // Remove any points 77 } 78 } 79 80 @Override 81 public void mouseEntered(MouseEvent e) { 82 setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR)); 83 } 84 85 @Override 86 public void mouseExited(MouseEvent e) { 87 setCursor(Cursor.getDefaultCursor()); 88 } 89 90 private Point start; // Stores cursor position on press 91 private Point last; // Stores cursor position on drag 92 private Element tempElement = null; // Stores a temporary element 93 private int buttonState = MouseEvent.NOBUTTON; // Records button state 94 private Graphics2D g2D = null; // Temporary graphics context 95 } 96 97 private Sketcher theApp; // The application object 98 }
4、窗口框架:
1 // Frame for the Sketcher application 2 import javax.swing.*; 3 import javax.swing.border.*; 4 import java.awt.event.*; 5 import java.awt.*; 6 7 import static java.awt.event.InputEvent.*; 8 import static java.awt.AWTEvent.*; 9 import static java.awt.Color.*; 10 import static Constants.SketcherConstants.*; 11 import static javax.swing.Action.*; 12 13 @SuppressWarnings("serial") 14 public class SketcherFrame extends JFrame { 15 // Constructor 16 public SketcherFrame(String title, Sketcher theApp) { 17 setTitle(title); // Set the window title 18 this.theApp = theApp; // Save app. object reference 19 setJMenuBar(menuBar); // Add the menu bar to the window 20 setDefaultCloseOperation(EXIT_ON_CLOSE); // Default is exit the application 21 22 createFileMenu(); // Create the File menu 23 createElementMenu(); // Create the element menu 24 createColorMenu(); // Create the element menu 25 createToolbar(); 26 toolBar.setRollover(true); 27 getContentPane().add(toolBar, BorderLayout.NORTH); 28 } 29 30 // Create File menu item actions 31 private void createFileMenuActions() { 32 newAction = new FileAction("New", 'N', CTRL_DOWN_MASK); 33 openAction = new FileAction("Open", 'O', CTRL_DOWN_MASK); 34 closeAction = new FileAction("Close"); 35 saveAction = new FileAction("Save", 'S', CTRL_DOWN_MASK); 36 saveAsAction = new FileAction("Save As..."); 37 printAction = new FileAction("Print", 'P', CTRL_DOWN_MASK); 38 exitAction = new FileAction("Exit", 'X', CTRL_DOWN_MASK); 39 40 // Initialize the array 41 FileAction[] actions = {openAction, closeAction, saveAction, saveAsAction, printAction, exitAction}; 42 fileActions = actions; 43 44 // Add toolbar icons 45 newAction.putValue(LARGE_ICON_KEY, NEW24); 46 openAction.putValue(LARGE_ICON_KEY, OPEN24); 47 saveAction.putValue(LARGE_ICON_KEY, SAVE24); 48 saveAsAction.putValue(LARGE_ICON_KEY, SAVEAS24); 49 printAction.putValue(LARGE_ICON_KEY, PRINT24); 50 51 // Add menu item icons 52 newAction.putValue(SMALL_ICON, NEW16); 53 openAction.putValue(SMALL_ICON, OPEN16); 54 saveAction.putValue(SMALL_ICON, SAVE16); 55 saveAsAction.putValue(SMALL_ICON,SAVEAS16); 56 printAction.putValue(SMALL_ICON, PRINT16); 57 58 // Add tooltip text 59 newAction.putValue(SHORT_DESCRIPTION, "Create a new sketch"); 60 openAction.putValue(SHORT_DESCRIPTION, "Read a sketch from a file"); 61 closeAction.putValue(SHORT_DESCRIPTION, "Close the current sketch"); 62 saveAction.putValue(SHORT_DESCRIPTION, "Save the current sketch to file"); 63 saveAsAction.putValue(SHORT_DESCRIPTION, "Save the current sketch to a new file"); 64 printAction.putValue(SHORT_DESCRIPTION, "Print the current sketch"); 65 exitAction.putValue(SHORT_DESCRIPTION, "Exit Sketcher"); 66 } 67 68 // Create the File menu 69 private void createFileMenu() { 70 JMenu fileMenu = new JMenu("File"); // Create File menu 71 fileMenu.setMnemonic('F'); // Create shortcut 72 createFileMenuActions(); // Create Actions for File menu item 73 74 // Construct the file drop-down menu 75 fileMenu.add(newAction); // New Sketch menu item 76 fileMenu.add(openAction); // Open sketch menu item 77 fileMenu.add(closeAction); // Close sketch menu item 78 fileMenu.addSeparator(); // Add separator 79 fileMenu.add(saveAction); // Save sketch to file 80 fileMenu.add(saveAsAction); // Save As menu item 81 fileMenu.addSeparator(); // Add separator 82 fileMenu.add(printAction); // Print sketch menu item 83 fileMenu.addSeparator(); // Add separator 84 fileMenu.add(exitAction); // Print sketch menu item 85 menuBar.add(fileMenu); // Add the file menu 86 } 87 88 // Create Element menu actions 89 private void createElementTypeActions() { 90 lineAction = new TypeAction("Line", LINE, 'L', CTRL_DOWN_MASK); 91 rectangleAction = new TypeAction("Rectangle", RECTANGLE, 'R', CTRL_DOWN_MASK); 92 circleAction = new TypeAction("Circle", CIRCLE,'C', CTRL_DOWN_MASK); 93 curveAction = new TypeAction("Curve", CURVE,'U', CTRL_DOWN_MASK); 94 95 // Initialize the array 96 TypeAction[] actions = {lineAction, rectangleAction, circleAction, curveAction}; 97 typeActions = actions; 98 99 // Add toolbar icons 100 lineAction.putValue(LARGE_ICON_KEY, LINE24); 101 rectangleAction.putValue(LARGE_ICON_KEY, RECTANGLE24); 102 circleAction.putValue(LARGE_ICON_KEY, CIRCLE24); 103 curveAction.putValue(LARGE_ICON_KEY, CURVE24); 104 105 // Add menu item icons 106 lineAction.putValue(SMALL_ICON, LINE16); 107 rectangleAction.putValue(SMALL_ICON, RECTANGLE16); 108 circleAction.putValue(SMALL_ICON, CIRCLE16); 109 curveAction.putValue(SMALL_ICON, CURVE16); 110 111 // Add tooltip text 112 lineAction.putValue(SHORT_DESCRIPTION, "Draw lines"); 113 rectangleAction.putValue(SHORT_DESCRIPTION, "Draw rectangles"); 114 circleAction.putValue(SHORT_DESCRIPTION, "Draw circles"); 115 curveAction.putValue(SHORT_DESCRIPTION, "Draw curves"); 116 } 117 118 // Create the Elements menu 119 private void createElementMenu() { 120 createElementTypeActions(); 121 elementMenu = new JMenu("Elements"); // Create Elements menu 122 elementMenu.setMnemonic('E'); // Create shortcut 123 createRadioButtonDropDown(elementMenu, typeActions, lineAction); 124 menuBar.add(elementMenu); // Add the element menu 125 } 126 127 // Create Color menu actions 128 private void createElementColorActions() { 129 redAction = new ColorAction("Red", RED, 'R', CTRL_DOWN_MASK|ALT_DOWN_MASK); 130 yellowAction = new ColorAction("Yellow", YELLOW, 'Y', CTRL_DOWN_MASK|ALT_DOWN_MASK); 131 greenAction = new ColorAction("Green", GREEN, 'G', CTRL_DOWN_MASK|ALT_DOWN_MASK); 132 blueAction = new ColorAction("Blue", BLUE, 'B', CTRL_DOWN_MASK|ALT_DOWN_MASK); 133 134 // Initialize the array 135 ColorAction[] actions = {redAction, greenAction, blueAction, yellowAction}; 136 colorActions = actions; 137 138 // Add toolbar icons 139 redAction.putValue(LARGE_ICON_KEY, RED24); 140 greenAction.putValue(LARGE_ICON_KEY, GREEN24); 141 blueAction.putValue(LARGE_ICON_KEY, BLUE24); 142 yellowAction.putValue(LARGE_ICON_KEY, YELLOW24); 143 144 // Add menu item icons 145 redAction.putValue(SMALL_ICON, RED16); 146 blueAction.putValue(SMALL_ICON, BLUE16); 147 greenAction.putValue(SMALL_ICON, GREEN16); 148 yellowAction.putValue(SMALL_ICON, YELLOW16); 149 150 // Add tooltip text 151 redAction.putValue(SHORT_DESCRIPTION, "Draw in red"); 152 blueAction.putValue(SHORT_DESCRIPTION, "Draw in blue"); 153 greenAction.putValue(SHORT_DESCRIPTION, "Draw in green"); 154 yellowAction.putValue(SHORT_DESCRIPTION, "Draw in yellow"); 155 } 156 157 // Create the Color menu 158 private void createColorMenu() { 159 createElementColorActions(); 160 colorMenu = new JMenu("Color"); // Create Elements menu 161 colorMenu.setMnemonic('C'); // Create shortcut 162 createRadioButtonDropDown(colorMenu, colorActions, blueAction); 163 menuBar.add(colorMenu); // Add the color menu 164 } 165 166 // Menu creation helper 167 private void createRadioButtonDropDown(JMenu menu, Action[] actions, Action selected) { 168 ButtonGroup group = new ButtonGroup(); 169 JRadioButtonMenuItem item = null; 170 for(Action action : actions) { 171 group.add(menu.add(item = new JRadioButtonMenuItem(action))); 172 if(action == selected) { 173 item.setSelected(true); // This is default selected 174 } 175 } 176 } 177 178 // Create toolbar buttons on the toolbar 179 private void createToolbar() { 180 for(FileAction action: fileActions){ 181 if(action != exitAction && action != closeAction) 182 addToolbarButton(action); // Add the toolbar button 183 } 184 toolBar.addSeparator(); 185 186 // Create Color menu buttons 187 for(ColorAction action:colorActions){ 188 addToolbarButton(action); // Add the toolbar button 189 } 190 191 toolBar.addSeparator(); 192 193 // Create Elements menu buttons 194 for(TypeAction action:typeActions){ 195 addToolbarButton(action); // Add the toolbar button 196 } 197 } 198 199 // Create and add a toolbar button 200 private void addToolbarButton(Action action) { 201 JButton button = new JButton(action); // Create from Action 202 button.setBorder(BorderFactory.createCompoundBorder( // Add button border 203 new EmptyBorder(2,5,5,2), // Outside border 204 BorderFactory.createRaisedBevelBorder())); // Inside border 205 button.setHideActionText(true); // No label on the button 206 toolBar.add(button); // Add the toolbar button 207 } 208 209 // Return the current drawing color 210 public Color getElementColor() { 211 return elementColor; 212 } 213 214 // Return the current element type 215 public int getElementType() { 216 return elementType; 217 } 218 219 // Set radio button menu checks 220 private void setChecks(JMenu menu, Object eventSource) { 221 if(eventSource instanceof JButton){ 222 JButton button = (JButton)eventSource; 223 Action action = button.getAction(); 224 for(int i = 0 ; i<menu.getItemCount() ; ++i) { 225 JMenuItem item = menu.getItem(i); 226 item.setSelected(item.getAction() == action); 227 } 228 } 229 } 230 231 // Inner class defining Action objects for File menu items 232 class FileAction extends AbstractAction { 233 // Create action with a name 234 FileAction(String name) { 235 super(name); 236 } 237 238 // Create action with a name and accelerator 239 FileAction(String name, char ch, int modifiers) { 240 super(name); 241 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 242 243 // Now find the character to underline 244 int index = name.toUpperCase().indexOf(ch); 245 if(index != -1) { 246 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 247 } 248 } 249 250 // Event handler 251 public void actionPerformed(ActionEvent e) { 252 // You will add action code here eventually... 253 } 254 } 255 256 // Inner class defining Action objects for Element type menu items 257 class TypeAction extends AbstractAction { 258 // Create action with just a name property 259 TypeAction(String name, int typeID) { 260 super(name); 261 this.typeID = typeID; 262 } 263 264 // Create action with a name and an accelerator 265 private TypeAction(String name,int typeID, char ch, int modifiers) { 266 this(name, typeID); 267 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 268 269 // Now find the character to underline 270 int index = name.toUpperCase().indexOf(ch); 271 if(index != -1) { 272 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 273 } 274 } 275 276 public void actionPerformed(ActionEvent e) { 277 elementType = typeID; 278 setChecks(elementMenu, e.getSource()); 279 } 280 281 private int typeID; 282 } 283 284 // Handles color menu items 285 class ColorAction extends AbstractAction { 286 // Create an action with a name and a color 287 public ColorAction(String name, Color color) { 288 super(name); 289 this.color = color; 290 } 291 292 // Create an action with a name, a color, and an accelerator 293 public ColorAction(String name, Color color, char ch, int modifiers) { 294 this(name, color); 295 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 296 297 // Now find the character to underline 298 int index = name.toUpperCase().indexOf(ch); 299 if(index != -1) { 300 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 301 } 302 } 303 304 public void actionPerformed(ActionEvent e) { 305 elementColor = color; 306 setChecks(colorMenu, e.getSource()); 307 } 308 309 private Color color; 310 } 311 312 // File actions 313 private FileAction newAction, openAction, closeAction, saveAction, saveAsAction, printAction, exitAction; 314 private FileAction[] fileActions; // File actions as an array 315 316 // Element type actions 317 private TypeAction lineAction, rectangleAction, circleAction, curveAction; 318 private TypeAction[] typeActions; // Type actions as an array 319 320 // Element color actions 321 private ColorAction redAction, yellowAction,greenAction, blueAction; 322 private ColorAction[] colorActions; // Color actions as an array 323 324 private JMenuBar menuBar = new JMenuBar(); // Window menu bar 325 private JMenu elementMenu; // Elements menu 326 private JMenu colorMenu; // Color menu 327 328 private Color elementColor = DEFAULT_ELEMENT_COLOR; // Current element color 329 private int elementType = DEFAULT_ELEMENT_TYPE; // Current element type 330 private JToolBar toolBar = new JToolBar(); // Window toolbar 331 private Sketcher theApp; // The application object 332 }
5、自定义常量包:
1 // Defines application wide constants 2 package Constants; 3 import java.awt.Color; 4 import javax.swing.*; 5 6 public class SketcherConstants { 7 // Path for images 8 public final static String imagePath = "E:/JavaProject/BeginningJava/Images/"; 9 10 // Toolbar icons 11 public final static Icon NEW24 = new ImageIcon(imagePath + "New24.gif"); 12 public final static Icon OPEN24 = new ImageIcon(imagePath + "Open24.gif"); 13 public final static Icon SAVE24 = new ImageIcon(imagePath + "Save24.gif"); 14 public final static Icon SAVEAS24 = new ImageIcon(imagePath + "SaveAs24.gif"); 15 public final static Icon PRINT24 = new ImageIcon(imagePath + "Print24.gif"); 16 17 public final static Icon LINE24 = new ImageIcon(imagePath + "Line24.gif"); 18 public final static Icon RECTANGLE24 = new ImageIcon(imagePath + "Rectangle24.gif"); 19 public final static Icon CIRCLE24 = new ImageIcon(imagePath + "Circle24.gif"); 20 public final static Icon CURVE24 = new ImageIcon(imagePath + "Curve24.gif"); 21 22 public final static Icon RED24 = new ImageIcon(imagePath + "Red24.gif"); 23 public final static Icon GREEN24 = new ImageIcon(imagePath + "Green24.gif"); 24 public final static Icon BLUE24 = new ImageIcon(imagePath + "Blue24.gif"); 25 public final static Icon YELLOW24 = new ImageIcon(imagePath + "Yellow24.gif"); 26 27 // Menu item icons 28 public final static Icon NEW16 = new ImageIcon(imagePath + "new16.gif"); 29 public final static Icon OPEN16 = new ImageIcon(imagePath + "Open16.gif"); 30 public final static Icon SAVE16 = new ImageIcon(imagePath + "Save16.gif"); 31 public final static Icon SAVEAS16 = new ImageIcon(imagePath + "SaveAs16.gif"); 32 public final static Icon PRINT16 = new ImageIcon(imagePath + "print16.gif"); 33 34 public final static Icon LINE16 = new ImageIcon(imagePath + "Line16.gif"); 35 public final static Icon RECTANGLE16 = new ImageIcon(imagePath + "Rectangle16.gif"); 36 public final static Icon CIRCLE16 = new ImageIcon(imagePath + "Circle16.gif"); 37 public final static Icon CURVE16 = new ImageIcon(imagePath + "Curve16.gif"); 38 39 public final static Icon RED16 = new ImageIcon(imagePath + "Red16.gif"); 40 public final static Icon GREEN16 = new ImageIcon(imagePath + "Green16.gif"); 41 public final static Icon BLUE16 = new ImageIcon(imagePath + "Blue16.gif"); 42 public final static Icon YELLOW16 = new ImageIcon(imagePath + "Yellow16.gif"); 43 44 // Element type definitions 45 public final static int LINE = 101; 46 public final static int RECTANGLE = 102; 47 public final static int CIRCLE = 103; 48 public final static int CURVE = 104; 49 50 // Initial conditions 51 public final static int DEFAULT_ELEMENT_TYPE = LINE; 52 public final static Color DEFAULT_ELEMENT_COLOR = Color.BLUE; 53 }
6、应用程序主程序:
1 // Sketching application 2 import javax.swing.*; 3 import java.awt.*; 4 import java.awt.event.*; 5 6 public class Sketcher { 7 public static void main(String[] args) { 8 theApp = new Sketcher(); // Create the application object 9 SwingUtilities.invokeLater(new Runnable() { 10 public void run() { 11 theApp.createGUI(); // Call GUI creator 12 } 13 }); 14 } 15 16 // Method to create the application GUI 17 private void createGUI() { 18 window = new SketcherFrame("Sketcher", this); // Create the app window 19 Toolkit theKit = window.getToolkit(); // Get the window toolkit 20 Dimension wndSize = theKit.getScreenSize(); // Get screen size 21 22 // Set the position to screen center & size to half screen size 23 window.setSize(wndSize.width/2, wndSize.height/2); // Set window size 24 window.setLocationRelativeTo(null); // Center window 25 26 window.addWindowListener(new WindowHandler()); // Add window listener 27 28 sketch = new SketcherModel(); // Create the model 29 view = new SketcherView(this); // Create the view 30 sketch.addObserver(view); // Register view with the model 31 window.getContentPane().add(view, BorderLayout.CENTER); 32 window.setVisible(true); 33 } 34 35 // Return a reference to the application window 36 public SketcherFrame getWindow() { 37 return window; 38 } 39 40 // Return a reference to the model 41 public SketcherModel getModel() { 42 return sketch; 43 } 44 45 // Return a reference to the view 46 public SketcherView getView() { 47 return view; 48 } 49 50 // Handler class for window events 51 class WindowHandler extends WindowAdapter { 52 // Handler for window closing event 53 @Override 54 public void windowClosing(WindowEvent e) { 55 // Code to be added here... 56 } 57 } 58 59 private SketcherModel sketch; // The data model for the sketch 60 private SketcherView view; // The view of the sketch 61 private SketcherFrame window; // The application window 62 private static Sketcher theApp; // The application object 63 }