2014年2月2日 星期日

Java Splash

一個完整的視窗應用程式,除了應用程式本身之外,均會在應用程式啟動時,顯示啟動畫面 (Splash),以說明應用程式之名稱、版本、版權等資訊,其使用時機通常是在應用程式需載入大量的視窗物件,為避免使用者等候,而顯示此啟動畫面,並同時載入物件。

Java SE 6.0新增支援顯示啟動畫面之java.awt.SplashScreen類別,使用SplashScreen類別處理啟動畫面是在Java Virtual Machine (JVM) 啟動之前所執行,也就是此部份的程序並不是交由JVM所執行的,而是以原生 (Native) 程式的方式執行,因此在顯示啟動畫面之後,使用者的等候時間是由JVM啟動開始計算。

SplashScreen類別的部份Java程式碼如下:


public static SplashScreen getSplashScreen() {
  if (GraphicsEnvironment.isHeadless()) {
    throw new HeadlessException();
  }

  System.loadLibrary("splashscreen");

  long ptr = _getInstance();
  if (ptr==0) {
    return null;
  }
  if (!_isVisible(ptr)) {
    return null;
  }
  return new SplashScreen(ptr);
}


由此可知,在getSplashScreen()方法中以System.loadLibrary()方法載入splashscreen原生函式,並以_getInstance()方法取得此函式的實體 (Instance),splashscreen原生函式包括以下之方法,為C語法 (參考splashscreen.h):


int DoSplashLoadMemory(void* pdata, int size); 
int DoSplashLoadFile(const char* filename);
void DoSplashInit(void);
void DoSplashClose(void);
void DoSplashSetFileJarName(const char* fileName, const char* jarName);


SplashScreen類別的方法有:
  • getSplashScreen()取得SplashScreen物件,以作為在JVM啟動之前,執行顯示啟動畫面的依據。
  • close()隱藏啟動畫面並釋放所有相關之系統資源,若不執行此方法,在Java AWT或Swing視窗物件顯示之後,SplashScreen物件亦會自動隱藏。
  • createGraphics()建立SplashScreen物件的繪圖Context,並回傳Graphics2D物件,以作為圖像之用。
  • getBounds()取得SplashScreen物件的邊界 (Bound),並回傳Rectangle物件,藉此可取得物件的水平 (Rectangle.x) 與垂直 (Rectangle.y) 位置、物件的寬度 (Rectangle.width) 與高度 (Rectangle.height)。
  • getSize()取得SplashScreen物件的尺寸 (Size),並回傳Dimension物件,藉此可取得物件的寬度 (Dimension.width) 與高度 (Dimension.height)。
  • isVisible()判斷SplashScreen物件是否可顯示,並回傳boolean型別,true代表可顯示,false則為隱藏。
  • update()更新SplashScreen物件。
請參考以下範例。欲建立顯示啟動畫面,首先以SplashScreen類別的getSplashScreen()方法取得SplashScreen物件,以作為在JVM啟動之前,執行啟動畫面之依據。若作業系統不支援此功能,則在執行getSplashScreen()方法時,將產生java.lang.UnsupportedOperationException之例外錯誤:


try {
  // 取得SplashScreen物件
  SplashScreen splashScreen = SplashScreen.getSplashScreen();

  if (splashScreen == null) {
    return;
  }
}
catch (UnsupportedOperationException ex) {
  ...
}


接著以
SplashScreen類別createGraphics()方法,建立SplashScreen物件之繪圖Context,以作為顯示啟動畫面之用:


try {
  // 建立SplashScreen物件之繪圖Context
  Graphics2D g2d = splashScreen.createGraphics();
  
  if (g2d == null) {
    return;
  }
}
catch (IllegalStateException ex) {
  ...
}


待繪圖Context建立之後,則以SplashScreen類別update()方法更新SplashScreen物件,其中以for迴圈產生時間延遲:


for(int i=0; i<100; i++) {
  // 更新SplashScreen物件
  splashScreen.update();
  
  try {
    Thread.sleep(20);
  }
  catch(InterruptedException ex) {...}
}


最後以SplashScreen類別close()方法,隱藏啟動畫面並釋放所有相關之系統資源。若不執行close()方法,在Java AWT或Java Swing視窗物件顯示之後,SplashScreen物件亦會自動隱藏:



splashScreen.close();


執行
SplashScreen時需注意的是程式載入SplashScreen物件所需使用的圖像,載入圖像並非由程式控制,而是由以下兩種方式處理:
  • 在Java直譯器 (java.exe) 的指令列加入 -splash 選項,其語法如下,其中[圖像檔案]選項可以包括目錄路徑為:
        java -splash:[圖像檔案] 類別檔案
        java -splash:[圖像檔案] -jar JAR檔案
    • 另一種方式是在建立Java Archive檔案所需之清單檔案manifest中,除了設定原有的Manifest-VersionMain-Class等項目之外,另加入SplashScreen-Image,以定義SplashScreen物件所需之圖像,但須注意的是,此設定不能包括目錄路徑,否則將無任何結果產生,例如:
            Manifest-Version: 1.0
            Main-Class: SplashDemo
            SplashScreen-Image: Splash.jpg

    【參考資料】

    [1] Java Platform, Standard Edition 7 API Specification.

    [2] 黃嘉輝,深入研究Java Swing (第二版),上奇資訊。

    © Chia-Hui Huang

    沒有留言:

    張貼留言