// This example is from _Java Examples in a Nutshell_. (http://www.oreilly.com) // Copyright (c) 1997 by David Flanagan // This example is provided WITHOUT ANY WARRANTY either expressed or implied. // You may study, use, modify, and distribute it for non-commercial purposes. // For any commercial use, see http://www.davidflanagan.com/javaexamples import java.applet.*; import java.awt.*; /** * An applet that displays a simple animation using double-buffering * and clipping **/ public class SmoothCircle extends Applet implements Runnable { int x = 150, y = 100, r=50; // Position and radius of the circle int dx = 8, dy = 5; // Trajectory of circle Dimension size; // The size of the applet Image buffer; // The off-screen image for double-buffering Graphics bufferGraphics; // A Graphics object for the buffer Thread animator; // Thread that performs the animation boolean please_stop; // A flag asking animation thread to stop /** Set up an off-screen Image for double-buffering */ public void init() { size = this.size(); buffer = this.createImage(size.width, size.height); bufferGraphics = buffer.getGraphics(); } /** Draw the circle at its current position, using double-buffering */ public void paint(Graphics g) { // Draw into the off-screen buffer. // Note, we could do even better clipping by setting the clip rectangle // of bufferGraphics to be the same as that of g. // In Java 1.1: bufferGraphics.setClip(g.getClip()); bufferGraphics.setColor(this.getBackground()); bufferGraphics.fillRect(0, 0, size.width, size.height); // clear the buffer bufferGraphics.setColor(Color.red); bufferGraphics.fillOval(x-r, y-r, r*2, r*2); // draw the circle // Then copy the off-screen buffer onto the screen g.drawImage(buffer, 0, 0, this); } /** Don't clear the screen; just call paint() immediately * It is important to override this method like this for double-buffering */ public void update(Graphics g) { paint(g); } /** The body of the animation thread */ public void run() { while(!please_stop) { // Bounce the circle if we've hit an edge. if ((x - r + dx < 0) || (x + r + dx > size.width)) dx = -dx; if ((y - r + dy < 0) || (y + r + dy > size.height)) dy = -dy; // Move the circle. x += dx; y += dy; // Ask the browser to call our paint() method to redraw the circle // at its new position. Tell repaint what portion of the applet needs // be redrawn: the rectangle containing the old circle and the // the rectangle containing the new circle. These two redraw requests // will be merged into a single call to paint() repaint(x-r-dx, y-r-dy, 2*r, 2*r); // repaint old position of circle repaint(x-r, y-r, 2*r, 2*r); // repaint new position of circle // Now pause 1/10th of a second before drawing the circle again. try { Thread.sleep(100); } catch (InterruptedException e) { ; } } animator = null; } /** Start the animation thread */ public void start() { if (animator == null) { please_stop = false; animator = new Thread(this); animator.start(); } } /** Stop the animation thread */ public void stop() { please_stop = true; } /** Allow the user to start and stop the animation by clicking */ public boolean mouseDown(Event e, int x, int y) { if (animator != null) please_stop = true; // if running request a stop else start(); // otherwise start it. return true; } }