Splash Screen Beginner Tutorial

Contents

Add a Splash Screen to a Java Application

I spent about a day researching how to do this. It is easy and takes just a few minutes once you know the procedure.

A Splash Screen is useful when the application has an initialization procedure that can take a significant amount of time before the application becomes responsive. It may also contain useful marketing or other information. In short the purpose of a splash screen is to entertain and inform the user while the program is busy getting ready to respond. Another benefit of showing a splash screen is that it helps the developer and end user understand how long each initialization step takes and if for some reason the initialization doesn't complete we know which step caused the problem

This project is designed for simplicity, once you understand it there's plenty you can do to make it look prettier.

If you're in a hurry

If you want to see the results here's the jar this tutorial produces File:SplashDemo.jar

Here is the NetBeans project File:SplashDemo.zip This was developed using NetBeans 6.8, Java 1.6.0_18; OpenJDK 64-Bit Server VM 16.0-b13. The results were tested on Windows XP, Vista and 7, and Linux (Centos 5, Ubuntu 10.04). I've also verified the project works with NetBeans 6.9.1 and 6.10m1.

In general, even if you are not using any IDE, you only need to take two steps to add a splash screen to your Java application:

  • Add an image to the jar (png, jpg, and gif formats are supported)
  • Update your executable jar manifest to specify the image to be used as a splash screen. Add:
SplashScreen-Image: <full or relative path to image in jar>

The above will show the splash screen when you build and run the jar but not when you run or debug from NetBeans. To see the splash and be able to debug splash modifications, go to the run properties and add the following to the VM options

-splash:<full or relative path to image in the project>

Note that if you use the IDE browse function for the splash image it will use the fully qualified path to the image, which is fine until the project is moved to a different location.

To customize the splash (add current task and a progress bar) use SplashScreen.getSplashScreen(); Which will allow you to draw over the splash image. See the sections below on how to quickly add a splash screen using the NetBeans IDE.

I would like to emphasize the "draw over" part. The Graphics Context of the image is available and we will use that to draw on the image. This is different from adding widgets to a Swing container.

Step by Step

To start, create an empty Java Application project in the NetBeans IDE.

File:EmptyProject.png

To add a Splash create an image but leave some space for additions in the next part. The image may be PNG, JPEG or GIF. For example in my image notice the blank area at the bottom, that is where the text and progress bar will go.

File:Splash.png

(Irrelevant fact: I am at the controls of the T28B in the picture, during a formation flying lesson).

Copy your Splash Screen image to the source folder in your project. Note: if you have more resources you may want to a separate resources folder.

Next, from the files tree open manifest.mf: File:ManifestSelect.png

Add the SplashScreen-Image property as shown.

Manifest-Version: 1.0
SplashScreen-Image: splashdemo/splash.png
X-COMMENT: Main-Class will be added automatically by build

Build the project and execute the jar. The Splash will display. At this point the splash screen will not display when you run or debug the project from the NetBeans IDE.

To get the Splash to display with the run or debug command from the IDE edit the Run properties and add to the VM options field

splash:src/<packagename>/splash.png

File:RunProperty.png

The reason we want the splash screen to display from inside the IDE is that it gives us the ability to debug the customization presented next.

Customizing the Splash to include task name and progress

We can make minor changes to the Splash at run time by overlaying simple text and graphic objects. If you want much more control you can replace the image with a Swing Panel (see Java Technical Article on Splash Screen [1]) but that is not part of this tutorial.

In this section we are going to overwrite part of our splash image with a text string and progress bar (actually a filled in rectangle). Remember I suggested we leave some blank area in our image for this. I reserved the bottom 15% or this use.

The following code can be put anywhere but I prefer static methods in the Main class. This allows us to call them from any class with a call like:

Main.splashText("Doing the first thing.");

To manage the Splash we create 3 methods:

  • splashInit - set object properties we need for the other methods
  • splashText - display a text string
  • splashProgress - update progress bar

Assume that the intialization is done in a method call appInit. Our appInit method will just display a list of strings one at a time and wait a second to simulate an initialization task.

The main method contains:

    public static void main(String[] args)
    {
        splashInit();           // initialize splash overlay drawing parameters
        appInit();              // simulate what an application would do 
                                // before starting
        if (mySplash != null)   // check if we really had a spash screen
            mySplash.close();   // if so we're now done with it
        
        // begin with the interactive portion of the program
    }

The methods supporting the Splash are described below:

    /**
     * Prepare the global variables for the other splash functions
     */
    private static void splashInit()
    {
        mySplash = SplashScreen.getSplashScreen();
        if (mySplash != null)
        {   // if there are any problems displaying the splash this will be null
            Dimension ssDim = mySplash.getSize();
            int height = ssDim.height;
            int width = ssDim.width;
            // stake out some area for our status information
            splashTextArea = new Rectangle2D.Double(15., height*0.88, width * .45, 32.);
            splashProgressArea = new Rectangle2D.Double(width * .55, height*.92, width*.4, 12 );

            // create the Graphics environment for drawing status info
            splashGraphics = mySplash.createGraphics();
            font = new Font("Dialog", Font.PLAIN, 14);
            splashGraphics.setFont(font);
            
            // initialize the status info
            splashText("Starting");
            splashProgress(0);
        }
    }

In the area we allocated for text we first erase a rectangle, then draw text. If you are unfamiliar with the text primitives the learning area covering text [2] is worthwhile reading. One improvement we could make is to determine if the text will fit in the area allocated and truncate it, or wrap it into multiple lines.

    /**
     * Display text in status area of Splash.  Note: no validation it will fit.
     * @param str - text to be displayed
     */
    public static void splashText(String str)
    {
        if (mySplash != null && mySplash.isVisible())
        {   // important to check here so no other methods need to know if there
            // really is a Splash being displayed

            // erase the last status text
            splashGraphics.setPaint(Color.LIGHT_GRAY);
            splashGraphics.fill(splashTextArea);

            // draw the text
            splashGraphics.setPaint(Color.BLACK);
            splashGraphics.drawString(str, (int)(splashTextArea.getX() + 10),(int)(splashTextArea.getY() + 15));

            // make sure it's displayed
            mySplash.update();
        }
    }

For a progress bar we are going to use a long thin rectangle and fill an appropriate percentage of it. If you are not familiar with the drawing primitives, the learning trail [3] is an excellent place to learn.

    /**
     * Display a (very) basic progress bar
     * @param pct how much of the progress bar to display 0-100
     */
    public static void splashProgress(int pct)
    {
        if (mySplash != null && mySplash.isVisible())
        {

            // Note: 3 colors are used here to demonstrate steps
            // erase the old one
            splashGraphics.setPaint(Color.LIGHT_GRAY);
            splashGraphics.fill(splashProgressArea);

            // draw an outline
            splashGraphics.setPaint(Color.BLUE);
            splashGraphics.draw(splashProgressArea);

            // Calculate the width corresponding to the correct percentage
            int x = (int) splashProgressArea.getMinX();
            int y = (int) splashProgressArea.getMinY();
            int wid = (int) splashProgressArea.getWidth();
            int hgt = (int) splashProgressArea.getHeight();

            int doneWidth = Math.round(pct*wid/100.f);
            doneWidth = Math.max(0, Math.min(doneWidth, wid-1));  // limit 0-width

            // fill the done part one pixel smaller than the outline
            splashGraphics.setPaint(Color.GREEN);
            splashGraphics.fillRect(x, y+1, doneWidth, hgt-1);

            // make sure it's displayed
            mySplash.update();
        }
    }
    /**
     * just a stub to simulate a long initialization task that updates
     * the text and progress parts of the status in the Splash
     */
    private static void appInit()
    {
        for(int i=1;i<=10;i++)
        {
            int pctDone = i * 10;
            splashText("Doing task #" + i);
            splashProgress(pctDone);
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException ex)
            {
                // ignore it
            }
        }
    }

Conclusion

There are several enhancements you can make to improve the look. Using an alpha channel to overwrite the image in a contrasting color is my first suggestion. Having a section of the screen with a constant color background, like this and erasing to that color looks better. I used different colors here to make it obvious what we are doing, I call it my Angry Fruit Salad color scheme.

References

  1. Java Technical Article on Splash Screen
  2. Java Learning Trail - Text
  3. Java Learning Trail - Geometry


This tutorial was written by Joseph Areeda a retired Software guy who does not guarantee that it is good for anything. Please feel free to add to it to contact him directly at areeda (at) netbeans (dot) org.

Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo