List C是一個簡單的動畫小程序,它是一個使用Runnable接口的例子。該例子可以放在網(wǎng)頁上,它需要從Applet類中派生出來。該小程序的目的是通過對一個接一個的圖象進行著色,從而顯示出動畫的效果。因為動畫占用了不少處理器時間,我們不打算在圖象著色的時候阻塞其他進程的運行。例如,假如打算停止動畫,我們不想等到它運行結束時,再調(diào)用stop方法。換句話說,我們可以讓小程序線程化。
List C: 動畫小程序
import java.applet.*; import java.awt.*; public class TstRunnable extends Applet implements Runnable { PRivate Thread m_Thread = null; private Image m_Images[]; private Image m_CurrentImage =null; private int m_nImgWidth = 0; private int m_nImgHeight = 0; private boolean m_fAllLoaded = false; private final int NUM_IMAGES = 18; public TstRunnable() { } private void displayImage(Graphics g) { if ( null != m_CurrentImage ) g.drawImage(m_CurrentImage,(getSize().width - m_nImgWidth) / 2, (getSize().height - m_nImgHeight) / 2, null); } public void paint(Graphics g) { if (null != m_CurrentImage) { Rectangle r = g.getClipBounds(); g.clearRect(r.x, r.y, r.width, r.height); displayImage(g); } else g.drawString("Loading images...", 10, 20); } // The Applets start method is called when the page is first shown. public void start() { if (m_Thread == null) { m_Thread = new Thread(this); m_Thread.start(); } } // The Applets stop method is called when the page is hidden. public void stop() { if (m_Thread != null) { m_Thread.stop(); m_Thread = null; } } // The run method is used by the thread // object we created in this start method. public void run() { int iWhichImage = 0; Graphics m_Graphics = getGraphics(); repaint(); m_Graphics = getGraphics(); m_Images = newImage[NUM_IMAGES]; MediaTracker tracker = new MediaTracker(this); String strImage; for (int i = 1; i <= NUM_IMAGES; i++) { m_Images[i-1] = getImage(getCodeBase(), "img" + new Integer(i).toString() + ".gif"); tracker.addImage(m_Images[i-1],0); } try { tracker.waitForAll(); m_fAllLoaded = !tracker.isErrorAny(); } catch (InterruptedException e) {} if (!m_fAllLoaded) { stop(); m_Graphics.drawString("Error loading images!", 10, 40); return; } // Assuming all images are the same // width and height. //------------------------------------ m_nImgWidth = m_Images[0].getWidth(this); m_nImgHeight = m_Images[0].getHeight(this); repaint(); while (true) { try { // Draw next image in animation. m_CurrentImage = m_Images[iWhichImage]; displayImage(m_Graphics); iWhichImage = (iWhichImage+1) % NUM_IMAGES; Thread.sleep(50); } catch (InterruptedException e) { stop(); } } } } 我們使用Runnable接口實現(xiàn)了線程,而沒有通過創(chuàng)建線程類的派生類的方式。使用Runnable接口,需要我們實現(xiàn)run方法。我們也需要創(chuàng)建Thread對象的一個實例,它最終是用來調(diào)用run方法的。在小程序中的start方法中,我們通過使用thread建構方法產(chǎn)生一個Thread對象的實例,其參數(shù)就是實現(xiàn)Runnable接口的任何類。 Thread 對象啟動已經(jīng)定義好的run 方法,而run方法是用來進行動畫顯示的。當然,從線程類中派生出一個類,并在Applet派生類中創(chuàng)建實例,我們可完成同樣的事情。該例子是用來演示Runnable接口的用法。
在我們接著讀下去之前,有幾個問題需要回答。你也許會問,瀏覽器調(diào)用Java小程序的start和stop方法嗎? run 方法是如何被調(diào)用的? 情況是這樣的,當瀏覽器啟動了一個內(nèi)部線程時,就相應地啟動了applet 的運行。當網(wǎng)頁顯示時,就啟動了applet的start 方法。Start方法創(chuàng)建一個線程對象,并把applet自身傳送給線程,以實現(xiàn)run方法。