对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. 使用Nexus搭建企业maven仓库(二)

    先阅读<使用Nexus搭建企业maven仓库(一)> http://blog.csdn.net/ouyida3/article/details/40747545 1.官网眼下最新的版本号是 ...

  2. mysql事务、触发器、视图、存储过程、函数

    存储过程: procedure 概念类似于函数,就是把一段代码封装起来, 当要执行这一段代码的时候,可以通过调用该存储过程来实现. 在封装的语句体里面,可以用if/else, case,while等控 ...

  3. Linux系统时间和硬件时间设置

    在Linux中有硬件时钟与系统时钟两种时钟.硬件时钟是指主机板上的时钟设备,也就是通常可在BIOS画面设定的时钟.系统时钟则是指kernel中的时钟.所有Linux相关指令与函数都是读取系统时钟的设定 ...

  4. c++ 对象指针参数和对象引用参数02

    对象指针作为函数参数和对象引用作为函数参数都比对象作为函数参数要用的更为普遍 传对象指针和传对象引用作为实参,那么实参在函数里发生了变话,那么相应的对象本身也会发生变化,二传递对象本身作为实参的话,实 ...

  5. ecshop 全目录说明

    ECShop 2.5.1 的结构图及各文件相应功能介绍     ECShop2.5.1_Beta upload 的目录           ┣ activity.php 活动列表           ...

  6. 在html中禁用自己主动完毕

    输入框输入内容时总是显示历史输入历史记录,现禁用的方法是加入一个属性: <input type="text name="txt_xm" autocomplete=& ...

  7. Blink: Chromium的新渲染引擎

    编自http://www.chromium.org/blink 关于blink Google Chrome/Chromium 从创始至今一直使用 WebKit(WebCore) 作为 HTML/CSS ...

  8. 初识google多语言通信框架gRPC系列(二)编译gRPC

    目录 一.概述 二.编译gRPC 三.C#中使用gRPC 四.C++中使用gRPC 无论通过哪种语言调用gRPC,都必须要编译gRPC,因为生成proto访问类时,除了产生标准的数据定义类之外,还需要 ...

  9. 你怎么知道你的网站K

    最近有朋友问我关于网站K问题,你怎么知道被提及哪些网站K方面.总结了六个方法后,,至于有没有其他办法.欢迎和我交流讨论. 检测方法是网站的搜索引擎惩罚:   首先要明白的是.搜索引擎不惩罚easy侦查 ...

  10. C#实现远程机器管理

    原文:C#实现远程机器管理 目前处于待离职状态,原先所有的工作都在进行交接,过程当中不乏有很多先前整理的和动手尝试实现的功能:我的主页中已经列出来一部分内容,有兴趣的可以前往看一看. 接下来的内容主要 ...