Below, is a third example program. It illustrates the loading and playing of an audio clip and a sequence of images that comprise a simple animation. The user interface provides buttons to play the audio and to start and stop the animation. It also includes buttons to sped up and slow down the animation.
The program is structured as three classes:
- The main class (multimedia) supports the user interface and the looping of the animation, again using double buffering.
- The loading and playing of the audio clip is handled by a separate class (handleAudio), run as a separate thread.
- The animation sequence of images is loaded in a separate class and thread (handleImageClip). Loading is forced at the time the the thread is run, rather than wait until the animation sequence is actually begun. However, unlike the audio class/thread, the image loading class/thread returns an array of images to the control class where it is run within an animation loop.
import java.applet.*; import java.awt.*; import java.awt.event.*; public class multimedia extends Applet implements Runnable, ActionListener, WindowListener { String version = new String ("Version 1"); Thread runThread = null; Frame outerBox; Panel drawPanel, bottomPanel, buttonPanel; Button audioButton, startButton, stopButton, speedupButton, speeddownButton, quitButton; TextField message; HandleAudio handleAudio; HandleImageClip handleImageClip; Image imageClip []; int numberImages = 5; boolean imagesLoaded = false; boolean continueClip = false; Image offscreenImage; Graphics offscreenImageG; Graphics drawPanelG; Dimension d; int delay = 100; // ************* start public void start () { if ( runThread == null ) { runThread = new Thread ( this ); } // end if runThread.start (); } // end start // ************* stop public void stop () { if ( runThread != null ) { runThread.stop (); runThread = null; } // end stop handleAudio.stop(); handleImageClip.stop(); } // end stop // ************* init public void init() { buildUI (); handleAudio = new HandleAudio (this, "testaudio.au"); handleImageClip = new HandleImageClip (this, "clip", numberImages ); d = drawPanel.getSize (); drawPanelG = drawPanel.getGraphics (); offscreenImage = this.createImage ( d.width, d.height ); offscreenImageG = offscreenImage.getGraphics (); offscreenImageG.setColor ( Color.white ); offscreenImageG.fillRect ( 0, 0, d.width, d.height ); imageClip = new Image [ numberImages ]; } // end init // ************* run thread public void run ( ) { while ( true ) { while ( continueClip ) { try { for ( int i=0; i < numberImages; i++ ) { offscreenImageG.fillRect ( 0, 0, d.width, d.height ); offscreenImageG.drawImage ( imageClip[i], 40, 50-(i*10), this ); repaint(); Thread.sleep ( delay ); } // end for for ( int i=numberImages-1; i >= 0; i-- ) { offscreenImageG.fillRect ( 0, 0, d.width, d.height ); offscreenImageG.drawImage ( imageClip[i], 40, 50+i*10, this ); repaint(); Thread.sleep ( delay ); } // end for } // end try catch ( InterruptedException except) { System.out.println ( "Error running clip" ); return; } // end catch } // end while: continueClip } // end while: true } // end run // ************* update public void update ( Graphics g ) { paint ( g ); } // end update // ************* paint public void paint ( Graphics g ) { drawPanelG.drawImage ( offscreenImage, 0, 0, 400, 500, Color.white, this ); } // end paint //*********** Utility Methods *********** // ************* buildUI public void buildUI () { drawPanel = new Panel ( ); drawPanel.setBackground ( Color.white ); // *** build the buttonPanel panel buttonPanel = new Panel ( ); audioButton = new Button ( "Audio" ); startButton = new Button ( "Start" ); stopButton = new Button ( "Stop" ); speedupButton = new Button ( "Speed-up" ); speeddownButton = new Button ( "Slow-down" ); quitButton = new Button ( "Quit" ); audioButton.addActionListener ( this ); startButton.addActionListener ( this ); stopButton.addActionListener ( this ); speedupButton.addActionListener ( this ); speeddownButton.addActionListener ( this ); quitButton.addActionListener ( this ); buttonPanel.add ( audioButton ); buttonPanel.add ( startButton ); buttonPanel.add ( speedupButton ); buttonPanel.add ( speeddownButton ); buttonPanel.add ( stopButton ); buttonPanel.add ( quitButton ); // *** build the message display area message = new TextField ( "Messages Displayed Here", 80 ); message.setEditable ( false ); // *** build the bottom panel bottomPanel = new Panel ( ); bottomPanel.setLayout ( new BorderLayout ( ) ); bottomPanel.add ( "North", buttonPanel ); bottomPanel.add ( "South", message ); bottomPanel.setBackground (Color.white); // *** build outer frame outerBox = new Frame ( "Multimedia Demo" ); outerBox.addWindowListener ( this ); outerBox.add ( "Center", drawPanel ); outerBox.add ( "South", bottomPanel ); outerBox.setSize ( 400, 550 ); outerBox.setVisible ( true ); } // end buildUI //*********** Interface Methods *********** //**** ActionListener methods public void actionPerformed ( ActionEvent e ) { Object s = e.getSource(); if ( s == audioButton ) { handleAudio.play(); message.setText ( "Audio clip played." ); } // end audioButton if ( s == startButton ) { message.setText ( "Animation started." ); continueClip = true; if ( ! imagesLoaded ) { imageClip = handleImageClip.getImages(); imagesLoaded = true; System.out.println ( "Images transferred to imageClip in startButton" ); } // end if } // end startButton if ( s == speedupButton ) { delay = Math.max ( (int) (delay * 0.8), 10 ); message.setText ( "Animation sped up." ); } // end speedupButton if ( s == speeddownButton ) { delay = Math.min ( (int) (delay * 1.2), 1000 ); message.setText ( "Animation slowed down." ); } // end speeddownButton if ( s == stopButton ) { continueClip = false; message.setText ( "Animation stopped." ); } // end stopButton if ( s == quitButton ) { message.setText ( "Applet quitting." ); try {Thread.sleep ( 1000 );} catch ( InterruptedException ie) {;} handleAudio.stop(); outerBox.hide (); outerBox.dispose (); } // end quitButton } // end actionPerformed //**** WindowListener methods public void windowActivated ( WindowEvent e ) { } public void windowDeactivated ( WindowEvent e ) { } public void windowOpened ( WindowEvent e ) { } public void windowClosed ( WindowEvent e ) { } public void windowClosing ( WindowEvent e ) { this.hide (); outerBox.dispose (); } public void windowIconified ( WindowEvent e ) { } public void windowDeiconified ( WindowEvent e ) { } } // end multimedia //******************************* HandleAudio Class **************** class HandleAudio extends Thread { Applet source; String audioFile; URL base; AudioClip audioClip; HandleAudio ( Applet a, String af ) { super (); source = a; audioFile = af; init (); start(); } // end constructor private void init () { base = source.getDocumentBase(); } // end init public void run () { audioClip = source.getAudioClip ( base, audioFile ); } // end run public void play () { audioClip.play(); } // end run } // end handleAudio //******************************* HandleImageClip Class **************** class HandleImageClip extends Thread { Applet source; String imageFile; int numberImages; Image imageArray[]; URL base; Image tempImage; // to force load Graphics tempG; // to force load HandleImageClip ( Applet a, String iff, int n ) { super (); source = a; imageFile = iff; numberImages = n; init (); start (); } // end constructor private void init () { imageArray = new Image [ numberImages ]; base = source.getCodeBase(); tempImage = source.createImage ( 100, 100 ); tempG = tempImage.getGraphics(); System.out.println ("Images being loaded from base = "+base); } // end init public void run () { for ( int i = 0; i < numberImages; i++ ) { String imageName = new String (imageFile + Integer.toString(i) + ".jpg" ); imageArray[i] = source.getImage ( base, imageName ); tempG.drawImage ( imageArray[i], 0, 0, source ); // force actual load } // end for } // end run public Image [] getImages ( ) { return imageArray; } // end draw } // end HandleImageClipRun the applet