对Java应用最常见的抱怨就是启动时间太长。这是因为Java虚拟机花费一段时间去加载所有必需的类,特别是对Swing应用,它们需要从Swing和AWT类库代码中去抽取大量的内容。

用户并不喜欢应用程序花费大量时间去产生初始屏幕,他们甚至可能不知道首次启动是否成功的情况下尝试着多次启动该应用程序。
此问题的解决之首是采用闪屏,即迅速出现的小窗体,它可以告诉用户该应用程序成功启动了。
传统上,这对于Java应用来说很难实现。当然,我们可以在main方法开始之后立即呈现一个窗体,但是,main方法只有在类加载器加载了所有需要依赖的类之后才会被启动,而这一过程可能要等上一段时间。

Java SE6支持虚拟机在启动时立即显示一幅图像而解决了这个问题。有两种机制可以指定这幅图像,一种使用命令行参数-splash:

java -splash:myImage.png package1.package2.MyApp

myImage.png文件需要在当前目录,否则要写全路径,相对或绝对
另一种是在JAR文件的清单中指定
Main-Class:package1.package2.MyApp
SplashScreen-Image:myimage.gif
这幅图像会在第一个AWT窗体可视时立即自动消失。我们可以使用任何GIF、JPEG或PNG图像,动画GIF和透明(GIF和PNG)都可以得到支持
如果应用程序在达到main之后即可立即执行,就不用考虑使用SplashScreen.

package swing.splash;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.SplashScreen;
import java.awt.Toolkit;
import java.util.List;
import java.util.concurrent.TimeUnit; import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker; /*2015-7-7*/
public class SplashScreenTest {
private static SplashScreen splash;
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 300; public static void main(String[] args) throws InterruptedException {
init1();
SwingUtilities.invokeLater(new Runnable() { @Override
public void run() {
init2();
}
});
} protected static void init2() {
final Image img = Toolkit.getDefaultToolkit().getImage(splash.getImageURL());
final JFrame splashFrame = new JFrame();
splashFrame.setAlwaysOnTop(true);
splashFrame.setUndecorated(true);
final JPanel splashPanel = new JPanel() {
private static final long serialVersionUID = 1L; @Override
protected void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, null);
}
}; final JProgressBar progressBar = new JProgressBar();
progressBar.setStringPainted(true);
splashPanel.setLayout(new BorderLayout());
splashPanel.add(progressBar, BorderLayout.SOUTH); splashFrame.add(splashPanel);
splashFrame.setBounds(splash.getBounds());
splashFrame.setVisible(true); new SwingWorker<Void, Integer>() { @Override
protected Void doInBackground() throws Exception {
for (int i = 0; i < 100; i++) {
publish(i);
TimeUnit.SECONDS.sleep(1);
} return null;
} @Override
protected void process(List<Integer> chunks) {
for (Integer chunk : chunks) {
progressBar.setString("Loading module" + chunk);
progressBar.setValue(chunk);
System.out.println(chunk);
splashPanel.repaint();// because img is loaded asynchronously
}
} @Override
protected void done() {
splashFrame.setVisible(false);
JFrame frame = new JFrame();
frame.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("SplashScreenTest");
frame.setVisible(true);
frame.setLocationRelativeTo(null); } }; } private static void drawOnSplash(int percent) {
Rectangle bounds = splash.getBounds();
Graphics2D g = splash.createGraphics();
int height = 20;
int x = 2;
int y = bounds.height - height - 4;
int width = bounds.width - 4;
Color brightPurple = new Color(76, 36, 121);
g.setColor(brightPurple);
g.fillRect(x, y, width * percent / 100, height);
splash.update();
} private static void init1() throws InterruptedException {
splash = SplashScreen.getSplashScreen();
if (splash == null) {
System.err.println("Did you specify a splash image with -splash or in the manifest");
System.exit(1);
} for (int i = 0; i < 100; i++) {
drawOnSplash(i);
System.out.println("init1:"+i);
TimeUnit.SECONDS.sleep(1);
} } }

Tips:

SplashScreen是Singleton,因此不能创建自己的SplashScreen对象。如果在命令行或清单(MANIFEST.MF)中没有设置任何SplashScreen,getSplashScreen方法将返回null.

SplashScreenDemo的更多相关文章

随机推荐

  1. VMware vSphere 服务器虚拟化之二十七桌面虚拟化之View中使用Thinapp软件虚拟化

    VMware vSphere 服务器虚拟化之二十七桌面虚拟化之View中使用Thinapp软件虚拟化 VMware ThinApp 应用程序虚拟化软件是无代理解决方案,通过将应用程序隔离并封装为EXE ...

  2. Cordova CLI源码分析(三)——初始化

    本部分主要涉及以下三个文件 1 cli.js 2 cordova.js 3 events.js 通过前一篇package.json的分析,可以知道,当命令行执行cordova相关命令时,首先调用mai ...

  3. uva 11722 - Joining with Friend(概率)

    题目连接:uva 11722 - Joining with Friend 题目大意:你和朋友乘火车,而且都会路过A市.给定两人可能到达A市的时段,火车会停w.问说两人能够见面的概率. 解题思路:y = ...

  4. ok6410 u-boot-2012.04.01移植七完善u-boot移植(u-boot移植结束)

    继ok6410 u-boot-2012.04.01移植六后,开发板已支持MLC NAND.DM9000等.但还需要完善比如环境变量.mtdpart分区.裁剪.制作补丁等.下面的工作就是完善移植的u-b ...

  5. 基于.net开发chrome核心浏览器【四】

    原文:基于.net开发chrome核心浏览器[四] 一: 上周去北京出差,给国家电网的项目做架构方案,每天都很晚睡,客户那边的副总也这样拼命工作. 累的不行了,直接导致第四篇文章没有按时发出来. 希望 ...

  6. js 自定义方法 实现停留几秒 sleep

    function sleep(numberMillis) { var now = new Date(); var exitTime = now.getTime() + numberMillis; wh ...

  7. 此文本文件包含的数据无法放置在一个工作表中 gb2312

    excel导入csv,csv要从unicode转为gb2312, 否则提示:此文本文件包含的数据无法放置在一个工作表中

  8. HDU 4380 Farmer Greedy 计算几何+bitset

    枚举直线,对于直线的某个点在直线的左端还是右端,能够状压出一个数.用bitset记录. 然后三角形就是3个bitset&一下 #include <cstdio> #include ...

  9. ViewPager.getChildCount() 含义

    viewpager.getChildCount() 非常easy误解成viewpager子页面的size.它和getCount还是有差别的 getChildCount() 是表示当前可见页size 比 ...

  10. Oracle 收集统计信息11g和12C在差异

    Oracle 基于事务临时表11g和12C下,能看到临时表后收集的统计数据,前者记录被清除,后者没有,这是一个很重要的不同. 关于使用企业环境12C,11g,使用暂时表会造成时快时慢.之前我有帖子ht ...