程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java Applet動畫設計

Java Applet動畫設計

編輯:關於JAVA

Applet是在浏覽器中運行的小程序,Java也是從Applet開始風靡世界的。通過編寫這個Applet,我們可以學習到如下知識:

1. Applet及JApplet中的主要接口

2. 圖像的裝載及MediaTracker的使用

3. 線程的使用及多個線程直接的通訊

4. Thread.join()方法的使用

5. volatile關鍵字的使用

首先看看運行效果:點擊運行

動畫的主要部分是一個Applet,從codebase中讀取一組圖片文件,然後每隔1秒輪換顯示一張。代碼如下:

import javax.swing.JApplet;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
public class Animate extends JApplet
{
  //圖片數量
  private static final int NUM_OF_PIC = 4;
  int count;
  Image pics[];
  TimerThread timer;
  public void init()
  {
   count = 1;
   pics = new Image[NUM_OF_PIC];
   MediaTracker tracker = new MediaTracker(this);
   for(int i = 0; i<NUM_OF_PIC; i++)
   {
    //將圖片按照0,1,...,NUM_OF_PIC -1,放置在目錄中,格式為.jpg
    pics[i] = getImage(getCodeBase(), new Integer(i).toString()+".jpg");
    tracker.addImage(pics[i], 0);
   }
   tracker.checkAll(true);
  }
  public void start()
  {
   timer = new TimerThread(this, 1000);
   timer.start();
  }
  public void stop()
  {
   timer.shouldRun = false;
   try
   {
    timer.join();
    //等待timer線程退出
   }
   catch (InterruptedException e){};
  }
  public void paint(Graphics g)
   {
    g.drawImage(pics[count++], 0, 0, null);
    if(count == NUM_OF_PIC) count = 0;
   }
}

動畫的控制由一個專門的線程TimerThread進行處理,

import java.awt.Component;
public class TimerThread extends Thread
{
  Component comp;
  int timediff;
  // shouldRun聲明為volatile
  volatile boolean shouldRun;
  public TimerThread(Component comp, int timediff)
  {
   super("TimerThread(" + timediff + " millseconds");
   this.comp = comp;
   this.timediff = timediff;
   shouldRun = true;
  }
  public void run()
  {
   while(shouldRun)
   {
    try
    {
     comp.repaint();
     sleep(timediff);
    }
    catch (Exception e){}
   }
  }
}

MediaTracker的使用

在Applet中獲取一個圖像文件,可以調用Applet的getImage()方法。但是getImage方法會在調用後馬上返回,如果此時馬上使用getImage獲取的Image對象,而這時Image對象並沒有真正裝載或者裝載完成。所以,我們在使用圖像文件時,使用java.awt包中的MediaTracker跟蹤一個Image對象的裝載,可以保證所有圖片都加載完畢。使用MediaTracker需要如下三個步驟:

1、實例化一個MediaTracker,注意要將顯示圖片的Component對象作為參數傳入。

MediaTracker tracker = new MediaTracker(this);

2、將要裝載的Image對象加入MediaTracker

pics[i] = getImage(getCodeBase(),
new Integer(i).toString()+".jpg");
tracker.addImage(pics[i], 0);

3、調用MediaTracker的checkAll()方法,等待裝載過程的結束。

tracker.checkAll(true);

Thread.join()的使用

我們在Animate的stop方法中調用timer的join()方法,將timer線程連接(join)到當前線程,當前線程會一致會等待timer線程運行結束後,timer.join()方法才會返回。如果當前線程在等待timer返回的過程中,被其它線程中斷了,那麼當前線程會拋出InterruptedException。如果不使用Thread的join方法,那麼只能通過輪詢timer線程的狀態進行判斷了:

while (timer.isAlive())
{
  try
  {
   Thread.sleep(50);
  }
  catch (InterruptedException e) {}
}

顯然這種辦法和使用join方法相比,會浪費cpu資源,同時也會浪費一些等待時間,因為當前線程每隔一段時間去查詢timer線程是否還存活,可能在timer線程已經結束了,但是當前線程還是要等待一段時間才能去監測它。

關於volatile

我們知道,在Java中設置變量值的操作,除了long和double類型的變量外都是原子操作,也就是說,對於變量值的簡單讀寫操作沒有必要進行同步。這在JVM 1.2之前,Java的內存模型實現總是從主存讀取變量,是不需要進行特別的注意的。而隨著JVM的成熟和優化,現在在多線程環境下volatile關鍵字的使用變得非常重要。在當前的Java內存模型下,線程可以把變量保存在本地內存(比如機器的寄存器)中,而不是直接在主存中進行讀寫。這就可能造成一個線程在主存中修改了一個變量的值,而另外一個線程還繼續使用它在寄存器中的變量值的拷貝,造成數據的不一致。要解決這個問題,只需要像在本程序中的這樣,把該變量聲明為volatile(不穩定的)即可,這就指示JVM,這個變量是不穩定的,每次使用它都到主存中進行讀取。一般說來,多任務環境下各任務間共享的標志都應該加volatile修飾。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved