对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. SVN的switch命令

    语法就不说了,文档有的是,主要是两个常用的用法: . 切换资源库(svn sw --relocate) [plain] view plaincopy svn sw --relocate <fro ...

  2. 非洲儿童(南阳oj1036)(馋)

    非洲小孩 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描写叙述 家住非洲的小孩,都非常黑.为什么呢? 第一.他们地处热带,太阳辐射严重. 第二,他们不常常洗澡.(常年缺水, ...

  3. WPF界面设计技巧(5)—自定义列表项呈现内容

    原文:WPF界面设计技巧(5)-自定义列表项呈现内容 接续上次的程序,稍微改动一下原有样式,并添加一个数据模板,我们就可以达成下面这样的显示功能: 鼠标悬停于文件列表项上,会在工具提示中显示图像缩略图 ...

  4. ConcurrentHashMap中的2的n次方幂上舍入方法(转)

    最近看JDK中的concurrentHashMap类的源码,其中有那么一个函数: /** * Returns a power of two table size for the given desir ...

  5. 局部敏感哈希-Locality Sensitive Hashing

    局部敏感哈希 转载请注明http://blog.csdn.net/stdcoutzyx/article/details/44456679 在检索技术中,索引一直须要研究的核心技术.当下,索引技术主要分 ...

  6. 收藏的Android很好用的组件或者框架。

    收藏的Android很好用的组件或者框架. android框架  先说两个站点: http://www.androidviews.net/ 非常好的国外开源码站,就是訪问速度有点慢啊 http://w ...

  7. pygame系列_mouse鼠标事件

    pygame.mouse提供了一些方法获取鼠标设备当前的状态 ''' pygame.mouse.get_pressed - get the state of the mouse buttons get ...

  8. SQLiteDatabase和Contentprovider

    SQLiteDatabase和Contentprovider这两个数据库,我一般是用前面一个,喜欢它的操作数据库的语句,简单明了,可惜有时遇到数据库同步的问题,有时我们需要在一个数据库下建立多个表,多 ...

  9. SessionFactory的创建和Session的获得

    1.当我们调用 Configuration config=new Configuration().configure(); 时候Hibernate会自己主动在当前的CLASSPATH中搜寻hibern ...

  10. Javascript语言精粹之正则表达式知识整理

    Javascript语言精粹之正则表达式知识整理 1.正则表达式思维导图 2.正则表达式常用示例 2.1 移除所有标签,只留下innerText var html = "<p>& ...