/* Applet scrolls a message, while a red oval grows from size zero to the full size of the applet. Two red bars across the applet lie above and below the path of the message. This is an example of animation using an off-screen canvas. David Eck, September 2, 1996 */ import java.awt.*; import java.applet.*; public class ScrollingMessage extends Applet implements Runnable { String message = "Hello World!"; // can be modified by an applet param with name "message" int message_x, message_y; // position where message is drawn int min_x, max_x; // largest and smallest values for message_x int bar1_y, bar2_y; // y coordinates for red lines across the applet int pulse_frames = 30; // number of frames it takes for red oval to grow to full size int scroll_frames = 100; // number of framed it takes for message to scroll across the screen Thread runner = null; // Thread for running the animation int sleepTime = 100; // Pause between frames, in milliseconds Image OSC = null; // the off-screen image Graphics OSC_graphics; // graphics context for OSC int width = -1; // width of OSC (value of -1 indicates it doesn't exist) int height = -1; // height of OSC public void init() { // just check for the parameter String param = getParameter("message"); if (param != null) message = param; } synchronized public void paint(Graphics g) { if (OSC != null) // if off-screen image exists, copy it to screen g.drawImage(OSC,0,0,this); else { // otherwise, fill the applet with the backgroudn color g.setColor(getBackground()); g.fillRect(0,0,size().width,size().height); } } public void update(Graphics g) { // redefine update() so that it doesn't erase the applet; // this will avoid flickering when the applet is redrawn paint(g); } public void start() { if (runner == null) { // create and start the thread runner = new Thread(this); runner.start(); } else if (runner.isAlive()) { // resume the thread, runner.resume(); // unless it is already dead } } public void stop() { if (runner.isAlive()) // suspend the thread, runner.suspend(); // if it is still alive } public void destroy() { if (runner.isAlive()) // if the thread is still running, runner.stop(); // then stop it runner = null; } synchronized void doResize(int w, int h) { // Resize the off-screen canvas to width w, height h // (presumably the new size of the applet). This is // called only by drawNextFrame(). The initial values // of instance variables width and height force this // to be called before any frames are drawn. OSC = null; width = w; height = h; OSC = createImage(width,height); // create off-screen canvas OSC_graphics = OSC.getGraphics(); Font font = getFont(); // font for drawing message, about 1/8 height of applet font = new Font("TimesRoman", Font.PLAIN, height/8); OSC_graphics.setFont(font); FontMetrics fm = getFontMetrics(font); // compute drawing parameters that depend on applet and font size message_y = (height - fm.getHeight()) / 2 + fm.getAscent() + fm.getLeading() / 2; bar1_y = message_y - fm.getAscent() - fm.getLeading(); bar2_y = message_y + fm.getLeading() + fm.getDescent(); min_x = -fm.stringWidth(message); max_x = width; } synchronized void drawNextFrame(int scroll_frame, int pulse_frame) { // Create one frame in the animation. scroll_frame gives // relative position of scrolling message; pulse_frame // gives relative size of growing oval. int w = size().width; // check if size of applet has changed int h = size().height; if (w != width || h != height) doResize(w,h); // compute drawing parameters that depend on which frame this is message_x = max_x - ((scroll_frame * (max_x-min_x)) / scroll_frames); int a = (width/2) - (pulse_frame*width)/(2*pulse_frames); // left edge for oval int b = (height/2) - (pulse_frame*height)/(2*pulse_frames); // top edge for oval OSC_graphics.setColor(Color.white); // fill the background OSC_graphics.fillRect(0,0,width,height); OSC_graphics.setColor(Color.red); // draw the oval OSC_graphics.fillOval(a,b,width-2*a,height-2*b); OSC_graphics.drawLine(0,bar1_y,width,bar1_y); // draw the bars (2 pixels high) OSC_graphics.drawLine(0,bar1_y+1,width,bar1_y+1); OSC_graphics.drawLine(0,bar2_y,width,bar2_y); OSC_graphics.drawLine(0,bar2_y-1,width,bar2_y-1); OSC_graphics.setColor(Color.black); // draw the message OSC_graphics.drawString(message,message_x,message_y); } public void run() { // subroutine to be executed by the thread int scroll_frame = 0; // frame number for scrolling int pulse_frame = 0; // frame number for growing oval while (true) { drawNextFrame(scroll_frame,pulse_frame); repaint(); scroll_frame++; if (scroll_frame > scroll_frames) scroll_frame = 0; pulse_frame++; if (pulse_frame > pulse_frames) pulse_frame = 0; try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } } // end of class ScrollingMessage