Splash screen

Splash screens are simple graphics(n. [测] 制图学;制图法;图表算法) which load quickly upon startup, and assure the user that the application is loading promptly. The SplashScreen class was added to JSE 6, and should be used if available.
If JSE 6 is not available, then the following technique is provided as an alternative(n. 二中择一;供替代的选择).
Various(adj. 各种各样的;多方面的) policies(n. 政策;保险单) for controlling the appearance and disappearance of the splash screen are possible. Here, the splash screen disappears when a main window has finished loading.

This example is also of interest since it demonstrates(vt. 证明;展示;论证) clearly that the launch thread is unusual(adj. 不寻常的;与众不同的;不平常的) - it’s distinct from the event dispatch thread, where most of the work of a Swing application takes place:
upon launch, the launch thread shows a splash screen, which activates the event dispatch thread once the splash screen is showing (or, more precisely, is “realized”), the launch thread acts as a “worker thread”, and can only close the splash screen indirectly, using EventQueue.invokeLater to properly inject an event into the event dispatch thread

package hirondelle.stocks.main;

import java.awt.*;
import java.net.URL;
import java.awt.image.ImageObserver;

/**
* Present a simple graphic to the user upon launch of the application, to 
* provide a faster initial response than is possible with the main window.
* 
* <P>Adapted from an 
* <a href=http://developer.java.sun.com/developer/qow/archive/24/index.html>item</a> 
* on Sun's Java Developer Connection.
*
* <P>This splash screen appears within about 2.5 seconds on a development 
* machine. The main screen takes about 6.0 seconds to load, so use of a splash 
* screen cuts down the initial display delay by about 55 percent.
* 
* <P>When JDK 6+ is available, its java.awt.SplashScreen class should be used instead 
* of this class.
*/
final class SplashScreen extends Frame {

  /**
  * Construct using an image for the splash screen.
  *  
  * @param aImageId must have content, and is used by  
  * {@link Class#getResource(java.lang.String)} to retrieve the splash screen image.
  */
  SplashScreen(String aImageId) {
    /* 
    * Implementation Note
    * Args.checkForContent is not called here, in an attempt to minimize 
    * class loading.
    */
    if (aImageId == null || aImageId.trim().length() == 0){
      throw new IllegalArgumentException("Image Id does not have content.");
    }
    fImageId = aImageId;
  }

  /**
  * Show the splash screen to the end user.
  *
  * <P>Once this method returns, the splash screen is realized, which means 
  * that almost all work on the splash screen should proceed through the event 
  * dispatch thread. In particular, any call to <tt>dispose</tt> for the 
  * splash screen must be performed in the event dispatch thread.
  */
  void splash(){
    initImageAndTracker();
    setSize(fImage.getWidth(NO_OBSERVER), fImage.getHeight(NO_OBSERVER));
    center();
    fMediaTracker.addImage(fImage, IMAGE_ID);
    try {
      fMediaTracker.waitForID(IMAGE_ID);
    }
    catch(InterruptedException ex){
      System.out.println("Cannot track image load.");
    }
    SplashWindow splashWindow = new SplashWindow(this,fImage);
  }

  // PRIVATE
  private final String fImageId;
  private MediaTracker fMediaTracker;
  private Image fImage;
  private static final ImageObserver NO_OBSERVER = null; 
  private static final int IMAGE_ID = 0;

  private void initImageAndTracker(){
    fMediaTracker = new MediaTracker(this);
    URL imageURL = SplashScreen.class.getResource(fImageId);
    fImage = Toolkit.getDefaultToolkit().getImage(imageURL);
  }

  /**
  * Centers the frame on the screen.
  *
  *<P>This centering service is more or less in {@link hirondelle.stocks.util.ui.UiUtil}; 
  * this duplication(n. 复制;副本;成倍) is justified only because the use of  
  * {@link hirondelle.stocks.util.ui.UiUtil} would entail(vt. 使需要,必需;承担;遗传给;蕴含) more class loading, which is 
  * not desirable for a splash screen.
  */
  private void center(){
    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    Rectangle frame = getBounds();
    setLocation((screen.width - frame.width)/2, (screen.height - frame.height)/2);
  }

  private final class SplashWindow extends Window {
    SplashWindow(Frame aParent, Image aImage) {
       super(aParent);
       fImage = aImage;
       setSize(fImage.getWidth(NO_OBSERVER), fImage.getHeight(NO_OBSERVER));
       Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
       Rectangle window = getBounds();
       setLocation((screen.width - window.width) / 2,(screen.height - window.height)/2);
       setVisible(true);
    }
    @Override public void paint(Graphics graphics) {
      if (fImage != null) {
        graphics.drawImage(fImage,0,0,this);
      }
    }
    private Image fImage;
  }

  /**
  * Developer test harness shows the splash screen for a fixed length of 
  * time, without launching the full application.
  */
  private static void main(String... aArgs){
    SplashScreen splashScreen = new SplashScreen("StocksMonitor.gif");
    splashScreen.splash();
    try {
      Thread.sleep(2000);
    }
    catch(InterruptedException ex) {
      System.out.println(ex);
    }
    System.exit(0);
  }
}

Here’s an example of a class which launches an application using the above SplashScreen:

package hirondelle.stocks.main;

import java.util.logging.*;
import java.awt.EventQueue;
import hirondelle.stocks.util.Util;
import hirondelle.stocks.util.Consts;

/**
* Launch the application using an older version of a splash screen.
*
*<P>Perform tasks in this order :
*<ul>
* <li>log basic system information 
* <li>promptly show a splash screen upon startup
* <li>show the main screen
* <li>remove the splash screen once the main screen is shown
*</ul>
*
* These tasks are performed in a thread-safe manner.
*/
public final class Launcher { 

  /**
  * Launch the application and display the main window.
  *
  * @param aArgs are ignored by this application, and may take any value.
  */
  public static void main (String... aArgs) {

    /*
    * Implementation Note:
    *
    * Note that the launch thread of any GUI application is in effect an initial 
    * worker thread - it is not the event dispatch thread, where the bulk of processing
    * takes place. Thus, once the launch thread realizes a window, then the launch 
    * thread should almost always manipulate such a window through 
    * EventQueue.invokeLater. (This is done for closing the splash 
    * screen, for example.)
    */

    //verifies that assertions are on:
    //  assert(false) : "Test";

    logBasicSystemInfo();
    showSplashScreen();
    showMainWindow();
    EventQueue.invokeLater(new SplashScreenCloser());
    fLogger.info("Launch thread now exiting...");
  }

  // PRIVATE 

  private static SplashScreen fSplashScreen;
  private static final Logger fLogger = Util.getLogger(Launcher.class);
  private static final String SPLASH_IMAGE = "StocksMonitor.gif";

  /**
  * Show a simple graphical splash screen, as a quick preliminary to the main screen.
  */
  private static void showSplashScreen(){
    fLogger.info("Showing the splash screen.");
    fSplashScreen = new SplashScreen(SPLASH_IMAGE);
    fSplashScreen.splash();
  }

  /**
  * Display the main window of the application to the user.
  */
  private static void showMainWindow(){
    fLogger.info("Showing the main window.");
    StocksMonitorMainWindow mainWindow = new StocksMonitorMainWindow();
  }

  /** 
  * Removes the splash screen. 
  *
  * Invoke this <tt>Runnable</tt> using 
  * <tt>EventQueue.invokeLater</tt>, in order to remove the splash screen
  * in a thread-safe manner.
  */
  private static final class SplashScreenCloser implements Runnable {
    @Override public void run(){
      fLogger.fine("Closing the splash screen.'");
      fSplashScreen.dispose();
    }
  }

  private static void logBasicSystemInfo() {
    fLogger.info("Launching the application...");
    fLogger.config(
      "Operating System: " + System.getProperty("os.name") + " " + 
      System.getProperty("os.version")
    );
    fLogger.config("JRE: " + System.getProperty("java.version"));
    fLogger.info("Java Launched From: " + System.getProperty("java.home"));
    fLogger.config("Class Path: " + System.getProperty("java.class.path"));
    fLogger.config("Library Path: " + System.getProperty("java.library.path"));
    fLogger.config("Application Name: " + Consts.APP_NAME + "/" + Consts.APP_VERSION);
    fLogger.config("User Home Directory: " + System.getProperty("user.home"));
    fLogger.config("User Working Directory: " + System.getProperty("user.dir"));
    fLogger.info("Test INFO logging.");
    fLogger.fine("Test FINE logging.");
    fLogger.finest("Test FINEST logging.");
  }
} 
  • Initial(最初的;字首的) threads, the threads that execute initial application code.
  • The event dispatch thread, where all event-handling code is executed. Most code that interacts with the Swing framework must also execute on this thread.
  • Worker threads, also known as background threads, where time-consuming background tasks are executed.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值