// Make it easy to access classes and methods of selected packages. import java.awt.*; import java.awt.event.*; import java.applet.*; /** * This class defines an applet for performing simple line drawing. It responds * to certain mouse movements, mouse clicks, and keyboard actions. * * Written by Jon Huhtala. */ public class App extends Applet implements KeyListener, MouseListener, MouseMotionListener { // Private instance variables for referencing the drawing area and color // palette. private MyCanvas canvas; private Palette palette; // Private instance variables for holding the starting and ending x-axis and // y-axis coordinates of a line to be drawn. private int startX; private int startY; private int endX; private int endY; // This method is automatically called when the browser loads the Web page // that launches the applet. Its purpose is to perform applet initialization. public void init() { // Specify the applet's layout and background color. setLayout(new BorderLayout()); setBackground(Color.lightGray); // Declare the main heading, set its font and alignment, and add it to the // top of the applet window. Label mainHdg = new Label("Drawing Applet"); mainHdg.setFont(new Font("SanSerif", Font.BOLD, 16)); mainHdg.setAlignment(Label.CENTER); add(mainHdg, BorderLayout.NORTH); // Instantiate and add the color palette to the bottom of the applet window. palette = new Palette(); add(palette, BorderLayout.SOUTH); // Instantiate the drawing area with a black background and add it to the // center of the applet window. canvas = new MyCanvas(500, 250, Color.black); add(canvas, BorderLayout.CENTER); // Register listeners for mouse clicks and mouse movements. Event handlers // are defined elsewhere within this class. canvas.addMouseListener(this); canvas.addMouseMotionListener(this); // Register a keyboard listener for the drawing area. canvas.addKeyListener(this); // Give the drawing area focus. Without focus, keyboard actions would NOT // be associated with the component. canvas.requestFocus(); } // This method implements the abstract method of the KeyListener // interface that handles the pressing and releasing of a key. It // receives a KeyEvent object as a parameter. public void keyTyped(KeyEvent e) { // If the user typed the "E" key, erase the drawing area. All other // keystrokes are ignored. if (e.getKeyChar() == 'E' || e.getKeyChar() == 'e') { canvas.erase(); } } // Provide shells to implement other abstract methods of the // KeyListener interface. public void keyPressed(KeyEvent e) {} public void keyReleased(KeyEvent e) {} // This method implements the abstract method of the MouseListener interface // to handle the user pressing a mouse button. It recieves a MouseEvent // object as a parameter. public void mousePressed(MouseEvent e) { // Save the mouse coordinates. They mark the starting point for drawing a // line segment. startX = e.getX(); startY = e.getY(); } // Provide shells to implement other abstract methods of the MouseListener // interface even though they aren't needed in this applet. public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} // This method implements the abstract method of the MouseMotionListener // interface to handle the user dragging the mouse (moving the mouse with a // button down). It recieves a MouseEvent object as a parameter. public void mouseDragged(MouseEvent e) { // The coordinates of the action mark the end of the line segment to be // drawn. endX = e.getX(); endY = e.getY(); // Set the pen color according to the current palette setting. canvas.setPen(palette.getColor()); // Draw the line. canvas.drawLine(startX, startY, endX, endY); // Save the mouse coordinates. They mark the starting point for drawing the // next line segment. startX = endX; startY = endY; } // This dummy method implements the other abstract method required by the // MouseMotionListener interface even though it isn't needed in this applet. public void mouseMoved(MouseEvent e) {} } // This class defines a canvas for drawing an image. The image is maintained // in memory but drawn to the screen whenever the canvas needs to be rendered. class MyCanvas extends Canvas { // Private instance variables for holding the width and height of the canvas. private int width; private int height; // Private instance variables for referencing the background color and pen // color. private Color background; private Color pen; // Private instance variable for referencing the image in memory. private Image pic; // This constructor instantiates the drawing canvas. It accepts arguments for // the canvas width, height, and background color. public MyCanvas(int iWidth, int iHeight, Color iBackground) { // Set the canvas' width, height, and background color. width = iWidth; height = iHeight; background = iBackground; } // This method can be called to set the pen color by passing it a Color // object. public void setPen(Color newPen) { pen = newPen; } // This method can be called to set the pen color by passing it integer values // representing the level of red, green, and blue light. public void setPen(int red, int green, int blue) { pen = new Color(red, green, blue); } // This method can be called to draw a line to the memory image and to the // screen. It receives the x and y coordinates of the starting and ending // points of the line. public void drawLine(int startX, int startY, int endX, int endY) { // Get the graphics context of the off-screen image. Graphics g = pic.getGraphics(); // Set the pen color and draw the line to the off-screen image. g.setColor(pen); g.drawLine(startX, startY, endX, endY); // Force the canvas to be re-drawn with the updated image. repaint(); } // This method can be called to erase the memory image and the screen. public void erase() { // Get the graphics context of the off-screen image. Graphics g = pic.getGraphics(); // Fill the entire off-sceen image with the background color. g.setColor(background); g.fillRect(0, 0, width, height); // Force the canvas to be re-drawn with the updated image. repaint(); } // This method overrides the addNotify() method of the Component class and // is automatically called prior to the canvas being displayed. It is used // here to create the off-screen image AFTER canvas construction and prior // to the canvas being displayed. The createImage() method can NOT be called // until this canvas object has been constructed!!! public void addNotify() { // Call the addNotify() method of the super class. super.addNotify(); // Construct the off-screen image by calling the createImage() method of // the Component class. pic = createImage(width, height); // Erase the off-screen image and force it to be drawn to the screen. erase(); } // This method overrides the update() method of the component class to prevent // the default action of erasing before painting. This method does not erase. // It simply re-paints (and produces less screen flicker). The method is // automatically called whenever the canvas must be rendered and receives the // canvas graphics context as a parameter. public void update(Graphics g) { // Call the paint method without erasing. paint(g); } // This method overrides the paint() method of the component class in order // to draw the memory image to the screen. It receives the graphics context // of the canvas as a parameter. public void paint(Graphics g) { // Draw the off-screen image to this canvas. g.drawImage(pic, 0, 0, this); } } // This class defines a panel with scroll bars that enable the user to set a // color based upon the red, green, and blue levels of light. It implements // the AdjustmentListener interface to help process changes to scrollbar // values. class Palette extends Panel implements AdjustmentListener { // Instance variables for referencing the red, green, and blue scrollbars. Scrollbar redBar; Scrollbar greenBar; Scrollbar blueBar; // Private instance variables for holding the level of red, green, and blue // light. private int redLevel; private int greenLevel; private int blueLevel; // Private instance variable for referencing the current ink color. private Blot blot; // This constructor builds the panel. public Palette() { // Set the background color and specify a grid layout with 4 rows and 2 // columns. setBackground(Color.lightGray); setLayout(new GridLayout(4,2)); // Set the initial color levels to maximum red, maximum green, and minimum // blue. This represents yellow. redLevel = 255; greenLevel = 255; blueLevel = 0; // Declare a label for the red level, set its font and alignment, and add // it to the first grid location. Label redLabel = new Label("Red Level"); redLabel.setFont(new Font("SanSerif", Font.BOLD, 12)); redLabel.setAlignment(Label.CENTER); add(redLabel); // Declare a scrollbar for the red level. It will be horizontal, have an // initial value based on the redLevel variable, a slider with a width of // 20, and a range from 0 to 255. Then, add it to the next grid location. redBar = new Scrollbar(Scrollbar.HORIZONTAL, redLevel, 20, 0, 255); add(redBar); // Register an adjustment listener for the red level scroll bar. redBar.addAdjustmentListener(this); // Declare a label for the green level, set its font and alignment, and add // it to the next grid location. Label greenLabel = new Label("Green Level"); greenLabel.setFont(new Font("SanSerif", Font.BOLD, 12)); greenLabel.setAlignment(Label.CENTER); add(greenLabel); // Declare a scrollbar for the green level. It will be horizontal, have an // initial value based on the greenLevel variable, a slider with a width of // 20, and a range from 0 to 255. Then, add it to the next grid location. greenBar = new Scrollbar(Scrollbar.HORIZONTAL, greenLevel, 20, 0, 255); add(greenBar); // Register an adjustment listener for the green level scroll bar. greenBar.addAdjustmentListener(this); // Declare a label for the blue level, set its font and alignment, and add // it to the next grid location. Label blueLabel = new Label("Blue Level"); blueLabel.setFont(new Font("SanSerif", Font.BOLD, 12)); blueLabel.setAlignment(Label.CENTER); add(blueLabel); // Declare a scrollbar for the blue level. It will be horizontal, have an // initial value based on the blueLevel variable, a slider with a width of // 20, and a range from 0 to 255. Then, add it to the next grid location. blueBar = new Scrollbar(Scrollbar.HORIZONTAL, blueLevel, 20, 0, 255); add(blueBar); // Register an adjustment listener for the blue level scroll bar. blueBar.addAdjustmentListener(this); // Declare a label for the current color, set its font and alignment, and // add it to the next grid location. Label blotLabel = new Label("Pen Color"); blotLabel.setFont(new Font("SanSerif", Font.BOLD, 12)); blotLabel.setAlignment(Label.RIGHT); add(blotLabel); // Instantiate a panel to display the current color. blot = new Blot(new Color(redLevel, greenLevel, blueLevel)); // Add the panel showing the current color to the next grid location. add(blot); } // This method implements the abstract method of the AdjustmentListener // interface that processes adjustment events (changes to scroll bar values). public void adjustmentValueChanged(AdjustmentEvent e) { // If the value of the red level has been changed, set the new value and // repaint the palette. if (e.getSource() == redBar) { redLevel = e.getValue(); repaint(); } // If the value of the green level has been changed, set the new value and // repaint the palette. if (e.getSource() == greenBar) { greenLevel = e.getValue(); repaint(); } // If the value of the blue level has been changed, set the new value and // repaint the palette. if (e.getSource() == blueBar) { blueLevel = e.getValue(); repaint(); } } // This method overrides the default paint() method for this panel. It // receives the panel's graphics context as a parameter. public void paint(Graphics g) { // Force the color panel to be repainted whenever the entire panel must be // repainted. blot.setColor(new Color(redLevel, greenLevel, blueLevel)); blot.repaint(); } // This method can be called to retrieve the current palette color. public Color getColor() { return new Color(redLevel, greenLevel, blueLevel); } } // This class defines a canvas to display an ink blot. class Blot extends Canvas { // Instance variable for referencing the current blot color. Color currentColor; // This constructor instantiates the blot with an initial color. public Blot(Color initColor) { // Call the superclass constructor and then set the current color. super(); currentColor = initColor; } // This method can be called to set a new color for the blot. public void setColor(Color newColor) { currentColor = newColor; } // Override the default update() method to prevent erasing the component // before it is redrawn. This prevents screen flicker. The component's // graphics context is received as a parameter. public void update(Graphics g) { // Call the paint method for the component without erasing. paint(g); } // This method overrides the default paint() method of the component. It // receives the component's graphics context as a parameter. public void paint(Graphics g) { // Draw a black oval. g.setColor(Color.black); g.fillOval(5, 1, 30, 20); // Draw a smaller oval in the current color inside the black oval. g.setColor(currentColor); g.fillOval(6, 2, 28, 18); } }