控制台程序。
为了可以选择系统支持的字体,我们定义了一个FontDialog类:
1 // Class to define a dialog to choose a font 2 import java.awt.*; 3 import javax.swing.*; 4 import java.awt.event.*; 5 import javax.swing.event.*; 6 import static Constants.SketcherConstants.*; 7 8 @SuppressWarnings("serial") 9 class FontDialog extends JDialog 10 implements ActionListener, // For buttons etc. 11 ListSelectionListener, // For list box 12 ChangeListener { // For the spinner 13 // Constructor 14 public FontDialog(SketcherFrame window) { 15 // Call the base constructor to create a modal dialog 16 super(window, "Font Selection", true); 17 font = window.getFont(); // Get the current font 18 19 // Create the dialog button panel 20 JPanel buttonPane = new JPanel(); // Create a panel to hold buttons 21 22 // Create and add the buttons to the buttonPane 23 buttonPane.add(ok = createButton("OK")); // Add the OK button 24 buttonPane.add(cancel = createButton("Cancel")); // Add the Cancel button 25 getContentPane().add(buttonPane, BorderLayout.SOUTH); // Add pane 26 27 // Code to create the data input panel 28 JPanel dataPane = new JPanel(); // Create the data entry panel 29 dataPane.setBorder(BorderFactory.createCompoundBorder( // Pane border 30 BorderFactory.createLineBorder(Color.BLACK), 31 BorderFactory.createEmptyBorder(5, 5, 5, 5))); 32 GridBagLayout gbLayout = new GridBagLayout(); // Create the layout 33 dataPane.setLayout(gbLayout); // Set the pane layout 34 GridBagConstraints constraints = new GridBagConstraints(); 35 36 // Create the font choice and add it to the input panel 37 JLabel label = new JLabel("Choose a Font"); 38 constraints.fill = GridBagConstraints.HORIZONTAL; 39 constraints.gridwidth = GridBagConstraints.REMAINDER; 40 gbLayout.setConstraints(label, constraints); 41 dataPane.add(label); 42 43 // Code to set up font list choice component 44 GraphicsEnvironment e = GraphicsEnvironment.getLocalGraphicsEnvironment(); 45 String[] fontNames = e.getAvailableFontFamilyNames(); // Get font names 46 47 fontList = new JList<>(fontNames); // Create list of font names 48 fontList.setValueIsAdjusting(true); // single event selection 49 fontList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 50 fontList.setSelectedValue(font.getFontName(),true); 51 fontList.addListSelectionListener(this); 52 fontList.setToolTipText("Choose a font"); 53 JScrollPane chooseFont = new JScrollPane(fontList); // Scrollable list 54 chooseFont.setMinimumSize(new Dimension(400,100)); 55 chooseFont.setWheelScrollingEnabled(true); // Enable mouse wheel scroll 56 57 // Panel to display font sample 58 JPanel display = new JPanel(true); 59 fontDisplay = new JLabel("Sample Size: x X y Y z Z"); 60 fontDisplay.setFont(font); 61 fontDisplay.setPreferredSize(new Dimension(350,100)); 62 display.add(fontDisplay); 63 64 //Create a split pane with font choice at the top and font display at the bottom 65 JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, 66 true, 67 chooseFont, 68 display); 69 gbLayout.setConstraints(splitPane, constraints); // Split pane constraints 70 dataPane.add(splitPane); // Add to the data pane 71 72 // Set up the size choice using a spinner 73 JPanel sizePane = new JPanel(true); // Pane for size choices 74 label = new JLabel("Choose point size: "); // Prompt for point size 75 sizePane.add(label); // Add the prompt 76 77 chooseSize = new JSpinner(new SpinnerNumberModel(font.getSize(), 78 POINT_SIZE_MIN, POINT_SIZE_MAX, POINT_SIZE_STEP)); 79 chooseSize.setValue(font.getSize()); // Set current font size 80 chooseSize.addChangeListener(this); 81 sizePane.add(chooseSize); 82 83 // Add spinner to pane 84 gbLayout.setConstraints(sizePane, constraints); // Set pane constraints 85 dataPane.add(sizePane); // Add the pane 86 87 // Set up style options using radio buttons 88 bold = new JRadioButton("Bold", (font.getStyle() & Font.BOLD) > 0); 89 italic = new JRadioButton("Italic", (font.getStyle() & Font.ITALIC) > 0); 90 bold.addItemListener(new StyleListener(Font.BOLD)); // Add button listeners 91 italic.addItemListener(new StyleListener(Font.ITALIC)); 92 JPanel stylePane = new JPanel(true); // Create style pane 93 stylePane.add(bold); // Add buttons 94 stylePane.add(italic); // to style pane... 95 gbLayout.setConstraints(stylePane, constraints); // Set pane constraints 96 dataPane.add(stylePane); // Add the pane 97 98 getContentPane().add(dataPane, BorderLayout.CENTER); 99 pack(); 100 setVisible(false); 101 } 102 103 // Create a dialog button 104 JButton createButton(String label) { 105 JButton button = new JButton(label); // Create the button 106 button.setPreferredSize(new Dimension(80,20)); // Set the size 107 button.addActionListener(this); // Listener is the dialog 108 return button; // Return the button 109 } 110 111 // Handler for button events 112 public void actionPerformed(ActionEvent e) { 113 if(e.getSource()== ok) { // If it's the OK button 114 ((SketcherFrame)getOwner()).setFont(font); // ...set selected font 115 } else { 116 font = ((SketcherFrame)getOwner()).getFont(); // Restore the current font 117 fontDisplay.setFont(font); 118 chooseSize.setValue(font.getSize()); // Restore the point size 119 fontList.setSelectedValue(font.getName(),true); 120 int style = font.getStyle(); 121 bold.setSelected((style & Font.BOLD) > 0); // Restore the 122 italic.setSelected((style & Font.ITALIC) > 0); // style options 123 } 124 // Now hide the dialog - for ok or cancel 125 setVisible(false); 126 } 127 128 // List selection listener method 129 public void valueChanged(ListSelectionEvent e) { 130 if(!e.getValueIsAdjusting()) { 131 font = new Font(fontList.getSelectedValue(), font.getStyle(), font.getSize()); 132 fontDisplay.setFont(font); 133 fontDisplay.repaint(); 134 } 135 } 136 137 // Handle spinner state change events 138 public void stateChanged(ChangeEvent e) { 139 int fontSize = ((Number)(((JSpinner)e.getSource()).getValue())).intValue(); 140 font = font.deriveFont((float)fontSize); 141 fontDisplay.setFont(font); 142 fontDisplay.repaint(); 143 } 144 145 // Iner class defining listeners for radio buttons 146 class StyleListener implements ItemListener { 147 public StyleListener(int style) { 148 this.style = style; 149 } 150 151 // Event handler for font style changes 152 public void itemStateChanged(ItemEvent e) { 153 int fontStyle = font.getStyle(); 154 if(e.getStateChange()==ItemEvent.SELECTED) { // If style was selected 155 fontStyle |= style; // turn it on in the font style 156 } else { 157 fontStyle &= ~style; // otherwise turn it off 158 } 159 font = font.deriveFont(fontStyle); // Get a new font 160 fontDisplay.setFont(font); // Change the label font 161 fontDisplay.repaint(); // repaint 162 } 163 private int style; // Style for this listener 164 } 165 166 private JListfontList; // Font list 167 private JButton ok; // OK button 168 private JButton cancel; // Cancel button 169 private JRadioButton bold; // Bold style button 170 private JRadioButton italic; // Italic style button 171 private Font font; // Currently selected font 172 private JSpinner chooseSize; // Font size options 173 private JLabel fontDisplay; // Font sample 174 }
然后在SketcherFrame中添加选择字体的菜单项:
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.Color.*; 9 import static Constants.SketcherConstants.*; 10 import static javax.swing.Action.*; 11 12 @SuppressWarnings("serial") 13 public class SketcherFrame extends JFrame implements ActionListener { 14 // Constructor 15 public SketcherFrame(String title, Sketcher theApp) { 16 setTitle(title); // Set the window title 17 this.theApp = theApp; // Save app. object reference 18 setJMenuBar(menuBar); // Add the menu bar to the window 19 setDefaultCloseOperation(EXIT_ON_CLOSE); // Default is exit the application 20 21 createFileMenu(); // Create the File menu 22 createElementMenu(); // Create the element menu 23 createColorMenu(); // Create the element menu 24 JMenu optionsMenu = new JMenu("Options"); // Create options menu 25 optionsMenu.setMnemonic('O'); // Create shortcut 26 menuBar.add(optionsMenu); // Add options to menu bar 27 28 createPopupMenu(); // Create popup 29 30 // Add the font choice item to the options menu 31 fontItem = new JMenuItem("Choose font..."); 32 fontItem.addActionListener(this); 33 optionsMenu.add(fontItem); 34 35 fontDlg = new FontDialog(this); // Create the font dialog 36 37 createToolbar(); 38 toolBar.setRollover(true); 39 40 JMenu helpMenu = new JMenu("Help"); // Create Help menu 41 helpMenu.setMnemonic('H'); // Create Help shortcut 42 43 // Add the About item to the Help menu 44 aboutItem = new JMenuItem("About"); // Create About menu item 45 aboutItem.addActionListener(this); // Listener is the frame 46 helpMenu.add(aboutItem); // Add item to menu 47 menuBar.add(helpMenu); // Add Help menu to menu bar 48 49 getContentPane().add(toolBar, BorderLayout.NORTH); // Add the toolbar 50 getContentPane().add(statusBar, BorderLayout.SOUTH); // Add the statusbar 51 } 52 53 // Create File menu item actions 54 private void createFileMenuActions() { 55 newAction = new FileAction("New", 'N', CTRL_DOWN_MASK); 56 openAction = new FileAction("Open", 'O', CTRL_DOWN_MASK); 57 closeAction = new FileAction("Close"); 58 saveAction = new FileAction("Save", 'S', CTRL_DOWN_MASK); 59 saveAsAction = new FileAction("Save As..."); 60 printAction = new FileAction("Print", 'P', CTRL_DOWN_MASK); 61 exitAction = new FileAction("Exit", 'X', CTRL_DOWN_MASK); 62 63 // Initialize the array 64 FileAction[] actions = {openAction, closeAction, saveAction, saveAsAction, printAction, exitAction}; 65 fileActions = actions; 66 67 // Add toolbar icons 68 newAction.putValue(LARGE_ICON_KEY, NEW24); 69 openAction.putValue(LARGE_ICON_KEY, OPEN24); 70 saveAction.putValue(LARGE_ICON_KEY, SAVE24); 71 saveAsAction.putValue(LARGE_ICON_KEY, SAVEAS24); 72 printAction.putValue(LARGE_ICON_KEY, PRINT24); 73 74 // Add menu item icons 75 newAction.putValue(SMALL_ICON, NEW16); 76 openAction.putValue(SMALL_ICON, OPEN16); 77 saveAction.putValue(SMALL_ICON, SAVE16); 78 saveAsAction.putValue(SMALL_ICON,SAVEAS16); 79 printAction.putValue(SMALL_ICON, PRINT16); 80 81 // Add tooltip text 82 newAction.putValue(SHORT_DESCRIPTION, "Create a new sketch"); 83 openAction.putValue(SHORT_DESCRIPTION, "Read a sketch from a file"); 84 closeAction.putValue(SHORT_DESCRIPTION, "Close the current sketch"); 85 saveAction.putValue(SHORT_DESCRIPTION, "Save the current sketch to file"); 86 saveAsAction.putValue(SHORT_DESCRIPTION, "Save the current sketch to a new file"); 87 printAction.putValue(SHORT_DESCRIPTION, "Print the current sketch"); 88 exitAction.putValue(SHORT_DESCRIPTION, "Exit Sketcher"); 89 } 90 91 // Create the File menu 92 private void createFileMenu() { 93 JMenu fileMenu = new JMenu("File"); // Create File menu 94 fileMenu.setMnemonic('F'); // Create shortcut 95 createFileMenuActions(); // Create Actions for File menu item 96 97 // Construct the file drop-down menu 98 fileMenu.add(newAction); // New Sketch menu item 99 fileMenu.add(openAction); // Open sketch menu item 100 fileMenu.add(closeAction); // Close sketch menu item 101 fileMenu.addSeparator(); // Add separator 102 fileMenu.add(saveAction); // Save sketch to file 103 fileMenu.add(saveAsAction); // Save As menu item 104 fileMenu.addSeparator(); // Add separator 105 fileMenu.add(printAction); // Print sketch menu item 106 fileMenu.addSeparator(); // Add separator 107 fileMenu.add(exitAction); // Print sketch menu item 108 menuBar.add(fileMenu); // Add the file menu 109 } 110 111 // Create Element menu actions 112 private void createElementTypeActions() { 113 lineAction = new TypeAction("Line", LINE, 'L', CTRL_DOWN_MASK); 114 rectangleAction = new TypeAction("Rectangle", RECTANGLE, 'R', CTRL_DOWN_MASK); 115 circleAction = new TypeAction("Circle", CIRCLE,'C', CTRL_DOWN_MASK); 116 curveAction = new TypeAction("Curve", CURVE,'U', CTRL_DOWN_MASK); 117 textAction = new TypeAction("Text", TEXT,'T', CTRL_DOWN_MASK); 118 119 // Initialize the array 120 TypeAction[] actions = {lineAction, rectangleAction, circleAction, curveAction, textAction}; 121 typeActions = actions; 122 123 // Add toolbar icons 124 lineAction.putValue(LARGE_ICON_KEY, LINE24); 125 rectangleAction.putValue(LARGE_ICON_KEY, RECTANGLE24); 126 circleAction.putValue(LARGE_ICON_KEY, CIRCLE24); 127 curveAction.putValue(LARGE_ICON_KEY, CURVE24); 128 textAction.putValue(LARGE_ICON_KEY, TEXT24); 129 130 // Add menu item icons 131 lineAction.putValue(SMALL_ICON, LINE16); 132 rectangleAction.putValue(SMALL_ICON, RECTANGLE16); 133 circleAction.putValue(SMALL_ICON, CIRCLE16); 134 curveAction.putValue(SMALL_ICON, CURVE16); 135 textAction.putValue(SMALL_ICON, TEXT16); 136 137 // Add tooltip text 138 lineAction.putValue(SHORT_DESCRIPTION, "Draw lines"); 139 rectangleAction.putValue(SHORT_DESCRIPTION, "Draw rectangles"); 140 circleAction.putValue(SHORT_DESCRIPTION, "Draw circles"); 141 curveAction.putValue(SHORT_DESCRIPTION, "Draw curves"); 142 textAction.putValue(SHORT_DESCRIPTION, "Draw text"); 143 } 144 145 // Create the Elements menu 146 private void createElementMenu() { 147 createElementTypeActions(); 148 elementMenu = new JMenu("Elements"); // Create Elements menu 149 elementMenu.setMnemonic('E'); // Create shortcut 150 createRadioButtonDropDown(elementMenu, typeActions, lineAction); 151 menuBar.add(elementMenu); // Add the element menu 152 } 153 154 // Create Color menu actions 155 private void createElementColorActions() { 156 redAction = new ColorAction("Red", RED, 'R', CTRL_DOWN_MASK|ALT_DOWN_MASK); 157 yellowAction = new ColorAction("Yellow", YELLOW, 'Y', CTRL_DOWN_MASK|ALT_DOWN_MASK); 158 greenAction = new ColorAction("Green", GREEN, 'G', CTRL_DOWN_MASK|ALT_DOWN_MASK); 159 blueAction = new ColorAction("Blue", BLUE, 'B', CTRL_DOWN_MASK|ALT_DOWN_MASK); 160 161 // Initialize the array 162 ColorAction[] actions = {redAction, greenAction, blueAction, yellowAction}; 163 colorActions = actions; 164 165 // Add toolbar icons 166 redAction.putValue(LARGE_ICON_KEY, RED24); 167 greenAction.putValue(LARGE_ICON_KEY, GREEN24); 168 blueAction.putValue(LARGE_ICON_KEY, BLUE24); 169 yellowAction.putValue(LARGE_ICON_KEY, YELLOW24); 170 171 // Add menu item icons 172 redAction.putValue(SMALL_ICON, RED16); 173 greenAction.putValue(SMALL_ICON, GREEN16); 174 blueAction.putValue(SMALL_ICON, BLUE16); 175 yellowAction.putValue(SMALL_ICON, YELLOW16); 176 177 // Add tooltip text 178 redAction.putValue(SHORT_DESCRIPTION, "Draw in red"); 179 greenAction.putValue(SHORT_DESCRIPTION, "Draw in green"); 180 blueAction.putValue(SHORT_DESCRIPTION, "Draw in blue"); 181 yellowAction.putValue(SHORT_DESCRIPTION, "Draw in yellow"); 182 } 183 184 // Create the Color menu 185 private void createColorMenu() { 186 createElementColorActions(); 187 colorMenu = new JMenu("Color"); // Create Elements menu 188 colorMenu.setMnemonic('C'); // Create shortcut 189 createRadioButtonDropDown(colorMenu, colorActions, blueAction); 190 menuBar.add(colorMenu); // Add the color menu 191 } 192 193 // Menu creation helper 194 private void createRadioButtonDropDown(JMenu menu, Action[] actions, Action selected) { 195 ButtonGroup group = new ButtonGroup(); 196 JRadioButtonMenuItem item = null; 197 for(Action action : actions) { 198 group.add(menu.add(item = new JRadioButtonMenuItem(action))); 199 if(action == selected) { 200 item.setSelected(true); // This is default selected 201 } 202 } 203 } 204 205 // Create pop-up menu 206 private void createPopupMenu() { 207 // Element menu items 208 popup.add(new JMenuItem(lineAction)); 209 popup.add(new JMenuItem(rectangleAction)); 210 popup.add(new JMenuItem(circleAction)); 211 popup.add(new JMenuItem(curveAction)); 212 popup.add(new JMenuItem(textAction)); 213 214 popup.addSeparator(); 215 216 // Color menu items 217 popup.add(new JMenuItem(redAction)); 218 popup.add(new JMenuItem(yellowAction)); 219 popup.add(new JMenuItem(greenAction)); 220 popup.add(new JMenuItem(blueAction)); 221 } 222 223 // Create toolbar buttons on the toolbar 224 private void createToolbar() { 225 for(FileAction action: fileActions){ 226 if(action != exitAction && action != closeAction) 227 addToolbarButton(action); // Add the toolbar button 228 } 229 toolBar.addSeparator(); 230 231 // Create Color menu buttons 232 for(ColorAction action:colorActions){ 233 addToolbarButton(action); // Add the toolbar button 234 } 235 236 toolBar.addSeparator(); 237 238 // Create Elements menu buttons 239 for(TypeAction action:typeActions){ 240 addToolbarButton(action); // Add the toolbar button 241 } 242 } 243 244 // Create and add a toolbar button 245 private void addToolbarButton(Action action) { 246 JButton button = new JButton(action); // Create from Action 247 button.setBorder(BorderFactory.createCompoundBorder( // Add button border 248 new EmptyBorder(2,5,5,2), // Outside border 249 BorderFactory.createRaisedBevelBorder())); // Inside border 250 button.setHideActionText(true); // No label on the button 251 toolBar.add(button); // Add the toolbar button 252 } 253 254 // Return the current drawing color 255 public Color getElementColor() { 256 return elementColor; 257 } 258 259 // Return the current element type 260 public int getElementType() { 261 return elementType; 262 } 263 264 // Return current text font 265 public Font getFont() { 266 return textFont; 267 } 268 269 // Method to set the current font 270 public void setFont(Font font) { 271 textFont = font; 272 } 273 274 // Retrieve the pop-up menu 275 public JPopupMenu getPopup() { 276 return popup; 277 } 278 279 // Set radio button menu checks 280 private void setChecks(JMenu menu, Object eventSource) { 281 if(eventSource instanceof JButton){ 282 JButton button = (JButton)eventSource; 283 Action action = button.getAction(); 284 for(int i = 0 ; ii) { 285 JMenuItem item = menu.getItem(i); 286 item.setSelected(item.getAction() == action); 287 } 288 } 289 } 290 291 // Handle About menu events 292 public void actionPerformed(ActionEvent e) { 293 if(e.getSource() == aboutItem) { 294 // Create about dialog with the app window as parent 295 JOptionPane.showMessageDialog(this, // Parent 296 "Sketcher Copyright Ivor Horton 2011", // Message 297 "About Sketcher", // Title 298 JOptionPane.INFORMATION_MESSAGE); // Message type 299 } else if(e.getSource() == fontItem) { // Set the dialog window position 300 fontDlg.setLocationRelativeTo(this); 301 fontDlg.setVisible(true); // Show the dialog 302 } 303 } 304 305 // Inner class defining Action objects for File menu items 306 class FileAction extends AbstractAction { 307 // Create action with a name 308 FileAction(String name) { 309 super(name); 310 } 311 312 // Create action with a name and accelerator 313 FileAction(String name, char ch, int modifiers) { 314 super(name); 315 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 316 317 // Now find the character to underline 318 int index = name.toUpperCase().indexOf(ch); 319 if(index != -1) { 320 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 321 } 322 } 323 324 // Event handler 325 public void actionPerformed(ActionEvent e) { 326 // You will add action code here eventually... 327 } 328 } 329 330 // Inner class defining Action objects for Element type menu items 331 class TypeAction extends AbstractAction { 332 // Create action with just a name property 333 TypeAction(String name, int typeID) { 334 super(name); 335 this.typeID = typeID; 336 } 337 338 // Create action with a name and an accelerator 339 private TypeAction(String name,int typeID, char ch, int modifiers) { 340 this(name, typeID); 341 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 342 343 // Now find the character to underline 344 int index = name.toUpperCase().indexOf(ch); 345 if(index != -1) { 346 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 347 } 348 } 349 350 public void actionPerformed(ActionEvent e) { 351 elementType = typeID; 352 setChecks(elementMenu, e.getSource()); 353 statusBar.setTypePane(typeID); 354 } 355 356 private int typeID; 357 } 358 359 // Handles color menu items 360 class ColorAction extends AbstractAction { 361 // Create an action with a name and a color 362 public ColorAction(String name, Color color) { 363 super(name); 364 this.color = color; 365 } 366 367 // Create an action with a name, a color, and an accelerator 368 public ColorAction(String name, Color color, char ch, int modifiers) { 369 this(name, color); 370 putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(ch, modifiers)); 371 372 // Now find the character to underline 373 int index = name.toUpperCase().indexOf(ch); 374 if(index != -1) { 375 putValue(DISPLAYED_MNEMONIC_INDEX_KEY, index); 376 } 377 } 378 379 public void actionPerformed(ActionEvent e) { 380 elementColor = color; 381 setChecks(colorMenu, e.getSource()); 382 statusBar.setColorPane(color); 383 } 384 385 private Color color; 386 } 387 388 // File actions 389 private FileAction newAction, openAction, closeAction, saveAction, saveAsAction, printAction, exitAction; 390 private FileAction[] fileActions; // File actions as an array 391 392 // Element type actions 393 private TypeAction lineAction, rectangleAction, circleAction, curveAction, textAction; 394 private TypeAction[] typeActions; // Type actions as an array 395 396 // Element color actions 397 private ColorAction redAction, yellowAction,greenAction, blueAction; 398 private ColorAction[] colorActions; // Color actions as an array 399 400 private JMenuBar menuBar = new JMenuBar(); // Window menu bar 401 private JMenu elementMenu; // Elements menu 402 private JMenu colorMenu; // Color menu 403 private JMenu optionsMenu; // Options menu 404 405 private StatusBar statusBar = new StatusBar(); // Window status bar 406 private FontDialog fontDlg; // The font dialog 407 408 private JMenuItem aboutItem; // About menu item 409 private JMenuItem fontItem; // Font chooser menu item 410 411 private JPopupMenu popup = new JPopupMenu("General"); // Window pop-up 412 private Color elementColor = DEFAULT_ELEMENT_COLOR; // Current element color 413 private int elementType = DEFAULT_ELEMENT_TYPE; // Current element type 414 private Font textFont = DEFAULT_FONT; // Default font for text elements 415 private JToolBar toolBar = new JToolBar(); // Window toolbar 416 private Sketcher theApp; // The application object 417 }