/** * SampleApplet.java * @version 1 * @author Robert Keller * * The purpose of this file is to give you the essentials of an applet * that includes animation capability (hence it is based on a thread) * and off-screen buffering to avoid flicker. * * It also demonstrates some simple event handling (AWT 1.0 style). * * Trace messages can be produced through System.out. * In a browser, they can be seen in the Netscape Java Console in the * Tools menu under the Communicator pullodown, * or (in theory, anyway) in Internet Explorer in the Java Messages window * accessible from the View pulldown menu. * * You will also need an html file to run this, and there should be one * attached to this document. Another option, the appletviewer application, * also requires the use of an html file. */ import java.applet.*; // applet classes import java.awt.*; // Abstract Window Toolkit classes // Below, 'extends Applet' is always required (inheriting from it). // 'implements Runnable' is required if we are going to run as a thread. // // This applet will use the default "layout manager", which determines // where things like Labels and Choices are positioned in the window when // added using the 'add' method. The default is currently FlowLayout. public class SampleApplet extends Applet implements Runnable { Label message = new Label("Click the mouse to move the shape there."); Color backgroundColor = Color.white, foregroundColor = Color.black; Font mainBold = new Font("Helvetica", Font.BOLD, 18); // The following array is used to initialize the Choice menu. String figure[] = {"Choose a Shape", "Rectangle", "Oval", "Text"}; static final int MESSAGE = 0; // indices of the above array static final int RECTANGLE = 1; static final int OVAL = 2; static final int TEXT = 3; int delayAmount = 25; // amount of delay between animation frames int xStart = 50; // starting position of figure int yStart = 100; int xNudge = 1; // amount by which to nudge figure int yNudge = 1; // in animating Shape currentShape; // current shape to be drawn Thread myThread; // thread for the code inside 'run' method Image image; // image for graphics buffer Graphics graphics; // graphics buffer Choice sampleChoice; // choice menu for samples /** * Initialize the applet. */ public void init() { setBackground(backgroundColor); // Set the background color. makeGraphicsBuffer(); // Make the graphics buffer. graphics.setFont(mainBold); // Set the default font for graphics. sampleChoice = new Choice(); // choice menu for selecting shape sampleChoice.setFont(mainBold); // Set the font for the Choice. add(sampleChoice); // Add Choice menu to applet. setExamples(sampleChoice, figure); // Set contents. message.setFont(mainBold); // Put a message in the applet. add(message); setShapeToRectangle(); // Set default shape. } /** * start the applet, called after init, and when page re-entered in browser */ public void start() { if( myThread == null ) { myThread = new Thread(this); myThread.start(); } } /** * stop the applet, called when the page is left from the browser */ public void stop() { myThread.stop(); } /** * run the applet */ public void run() { while( true ) // loop "forever" { drawStuff(graphics); // draw stuff in buffer repaint(); // repaint the buffer delay(delayAmount); // wait awhile currentShape.nudge(xNudge, yNudge); // nudge the shape } } /** * update is implicitly called by repaint() in the underlying Applet class. * It calls paint(Graphics). By over-riding, we are avoid * repainting the background as the default method does. * This helps avoid flicker. */ public void update(Graphics g) { paint(g); } /** * paint(Graphics) is called by update(Graphics), which is called * by repaint(). */ public void paint(Graphics g) { g.drawImage(image, 0, 0, null); } /** * Make a buffer for off-screen image. This creates an Image the * same size as the applet window. The graphics component of that * image is where the actual drawing is done. The image is then * painted to the screen in the 'paint' method. */ void makeGraphicsBuffer() { image = createImage(size().width, size().height); graphics = image.getGraphics(); } /** * Service an event from some screen object. * In the current example, the choice menu is the only such object. * This is called by the underlying system in a separate thread, not * byt the programmer. */ public boolean action(Event event, Object arg) { if( event.target == sampleChoice ) { switch( sampleChoice.getSelectedIndex() ) // position selected { case MESSAGE: break; // This is the message at top of the choice. case RECTANGLE: setShapeToRectangle(); break; case OVAL: setShapeToOval(); break; case TEXT: setShapeToText(); break; } } return super.action(event, arg); } /** * mouseDown is called by the Applet when the mouse button is depressed. * In the present applet, it will move the shape to the mouse position. * This is called by the underlying system in a separate thread, not * by the programmer. */ public boolean mouseDown(Event e, int x, int y) { currentShape.move(x, y); return true; } /** * Set the displayed shape to a 200 wide by 100 high red rectangle. */ void setShapeToRectangle() { currentShape = new Rectangle(xStart, yStart, 200, 100, Color.red); } /** * Set the displayed shape to a 200 wide by 100 high blue oval. */ void setShapeToOval() { currentShape = new Oval(xStart, yStart, 200, 100, Color.blue); } /** * Set the displayed shape to some witty text. */ void setShapeToText() { currentShape = new Text(xStart, yStart, "Applets are fun.", Color.green); } /** * Set up content of Choice menu. */ void setExamples(Choice choice, String figure[]) { for( int i = 0; i < figure.length; i++ ) { choice.addItem(figure[i]); } } /** * Draw whatever is desired for this cycle, clearing everything first. */ void drawStuff(Graphics graphics) { eraseEverything(graphics); currentShape.draw(graphics); } /** * Erase the graphics buffer by filling it with the background color. */ void eraseEverything(Graphics graphics) { graphics.setColor(backgroundColor); graphics.fillRect(0, 0, size().width, size().height); } /** * Delay execution a specified number of milliseconds. */ void delay(int milliseconds) { try // This is necessary, even tho' we don't plan on any exceptions. { myThread.sleep(milliseconds); } catch( Exception e ) { } } } // SampleApplet /** * An abstract base class representing shapes to be displayed in the animation. */ abstract class Shape { /** * horizontal position */ int x; /** * vertical position */ int y; /** * color of lines */ Color color; /** * base class constructor */ Shape(int x, int y, Color color) { this.x = x; this.y = y; this.color = color; } /** * Draw the shape on a Graphics object. */ abstract void draw(Graphics graphics); /** * Move the shape to a specific position. */ void move(int x, int y) { this.x = x; this.y = y; } /** * Move the shape by specified delta. */ void nudge(int xdelta, int ydelta) { x += xdelta; y += ydelta; } } /** * the Rectangle shape */ class Rectangle extends Shape { int width; int height; /** * Construct a rectangle. */ Rectangle(int x, int y, int width, int height, Color color) { super(x, y, color); this.width = width; this.height = height; } /** * Draw the Rectangle at its current position. */ void draw(Graphics graphics) { graphics.setColor(color); graphics.drawRect(x, y, width, height); } } /** * the Oval shape */ class Oval extends Shape { int width; int height; /** * Construct an Oval. */ Oval(int x, int y, int width, int height, Color color) { super(x, y, color); this.width = width; this.height = height; } /** * Draw the Oval at its current position. */ void draw(Graphics graphics) { graphics.setColor(color); graphics.drawOval(x, y, width, height); } } /** * the Text shape */ class Text extends Shape { /** * The text content of this Text shape. */ String string; /** * Construct a Text Shape. */ Text(int x, int y, String string, Color color) { super(x, y, color); this.string = string; } /** * Draw the Text at its current position. */ void draw(Graphics graphics) { graphics.setColor(color); graphics.drawString(string, x, y); } }