Painter has three menus: File, Draw, and Effects. As you'd expect, the File menu is used to create a new image, load an existing image, and save an image; here are the items in the File menu:
The Draw and Effects menus work together; you select a drawing tool from the Draw menu (such as the line-drawing tool), and you can also select various effects from the Effects menu (such as drop shadows, texture fill, and so on). The items you select in these menus will have a check mark displayed in front of them, and they will stay checked until you select another item that is incompatible (such as selecting the ellipse-drawing tool). Here are the items in the Draw menu:
And here are the possible effects you can use with the drawing tools from the Effects menu:
As before, the window the application draws is created in the application's constructor. And like the previous applications so far, this one is based on the Frame class. Here's what Painter's main method and constructor look like; the constructor adds the mouse listeners the application needs for drawing operations, and it constructs the menu system: public static void main(String[] args) { new Painter(); } public Painter() { setLayout(null); addMouseListener(this); addMouseMotionListener(this); menubar = new MenuBar(); menu1 = new Menu("File"); menu2 = new Menu("Draw"); menu3 = new Menu("Effects"); newMenuItem = new MenuItem("New"); menu1.add(newMenuItem); newMenuItem.addActionListener(this); openMenuItem = new MenuItem("Open..."); menu1.add(openMenuItem); openMenuItem.addActionListener(this); saveMenuItem = new MenuItem("Save As..."); menu1.add(saveMenuItem); saveMenuItem.addActionListener(this); colorMenuItem = new MenuItem("Select color..."); menu3.add(colorMenuItem); colorMenuItem.addActionListener(this); exitMenuItem = new MenuItem("Exit"); menu1.add(exitMenuItem); exitMenuItem.addActionListener(this); . . . The Painter application has many check box menu items, where a menu item stays checked until it's unchecked by the user or the code. Here is how those items are created in the constructor: linesMenuItem = new CheckboxMenuItem("Draw lines"); menu2.add(linesMenuItem); linesMenuItem.addItemListener(this); ellipsesMenuItem = new CheckboxMenuItem("Draw ellipses"); menu2.add(ellipsesMenuItem); ellipsesMenuItem.addItemListener(this); rectanglesMenuItem = new CheckboxMenuItem("Draw rectangles"); menu2.add(rectanglesMenuItem); rectanglesMenuItem.addItemListener(this); roundedMenuItem = new CheckboxMenuItem( "Draw rounded rectangles"); menu2.add(roundedMenuItem); roundedMenuItem.addItemListener(this); freehandMenuItem = new CheckboxMenuItem("Draw freehand"); menu2.add(freehandMenuItem); freehandMenuItem.addItemListener(this); plainMenuItem = new CheckboxMenuItem("Plain"); menu3.add(plainMenuItem); plainMenuItem.addItemListener(this); solidMenuItem = new CheckboxMenuItem("Solid fill"); menu3.add(solidMenuItem); solidMenuItem.addItemListener(this); gradientMenuItem = new CheckboxMenuItem("Gradient fill"); menu3.add(gradientMenuItem); gradientMenuItem.addItemListener(this); textureMenuItem = new CheckboxMenuItem("Texture fill"); menu3.add(textureMenuItem); textureMenuItem.addItemListener(this); transparentMenuItem = new CheckboxMenuItem("Transparent"); menu3.add(transparentMenuItem); transparentMenuItem.addItemListener(this); textMenuItem = new CheckboxMenuItem("Draw text"); menu2.add(textMenuItem); textMenuItem.addItemListener(this); thickMenuItem = new CheckboxMenuItem("Draw thick lines"); menu3.add(thickMenuItem); thickMenuItem.addItemListener(this); shadowMenuItem = new CheckboxMenuItem("Drop shadow"); menu3.add(shadowMenuItem); shadowMenuItem.addItemListener(this); menubar.add(menu1); menubar.add(menu2); menubar.add(menu3); setMenuBar(menubar); . . . Check box menu items are supported by the CheckboxMenuItem class, and you can see the significant methods of this class in Table 4.1.
Painter will also need a File dialog box for loading and saving images, so the constructor creates a new FileDialog object. Because the ImageIO class works with BufferedImage objects, the constructor also creates a buffered image and then displays the main window. Internally, the Painter application uses an Image object, named image, to do the drawing in. And there's also a dialog box of the same class put together for the Slapshot! application, OKCancelDialog, that Painter will use to read the text it's supposed to draw in the image. Here's how all this is set up in the constructor: dialog = new FileDialog(this, "File Dialog"); bufferedImage = new BufferedImage (imageWidth, imageHeight, BufferedImage.TYPE_INT_BGR ); setSize(400, 400); setTitle("Painter"); setVisible(true); image = createImage(imageWidth, imageHeight); textDialog = new OkCancelDialog(this, "Enter your text", true); . . . All that's left in the constructor is to read in the image, named tile.jpg, used for filling images with text. You can use any image file for texture fills, as long as you name it tile.jpg; this application comes with a default tile.jpg file. Finally, the constructor adds the window closer as usual: try{ File inputFile = new File("tile.jpg"); tileImage = ImageIO.read(inputFile); } catch (java.io.IOException ioe){ System.out.println("Need tile.jpg."); System.exit(0); } this.addWindowListener(new WindowAdapter(){ public void windowClosing( WindowEvent e){ System.exit(0); } } ); } Painter works by setting flags corresponding to the drawing operation or graphics effect you want to use and then checking those flags when it's time to do the actual drawing. |