A splash screen

G

Glenn McCall

I am trying to create a splash screen. I would like it to be visible for a
few seconds while the application is initialising. After a timer expires,
the splash screen will close automatically. I have all of this working just
fine.

However, at some point during the application initialisation, it creates the
main window. When this occurs, the main window appears on top of the splash
screen. I would prefer that the splash screen be "top most" when this
occurs.

I have tried various combinations of toFront() and toBack() with no success
whatsoever.

How can I keep my splash screen topmost - preferably without having to mess
with "lost focus" type of events? In VC++, I could do this by creating the
splash screen window with the "TOPMOST" attribute set - but I can't find a
similar attribute in the java window classes.

TIA - Glenn Mc

P.S. For what it is worth, I have attached some snippets of the code I am
using. SplashPanel extends JPanel and contains all of the components making
up the splash screen.


public class SqlManEditor extends JFrame {

private static JWindow splash;

private static void showSplash (final int duration) {
/* final JWindow */ splash = new JWindow ();
SplashPanel content = new SplashPanel ();

splash.setContentPane(content);
splash.pack ();

// Center the splash screen in the display.
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize ();
int x = (screen.width - content.getWidth()) / 2;
int y = (screen.height - content.getHeight()) / 2;
splash.setBounds (x, y, content.getWidth(), content.getHeight());

Thread r = new Thread () {
public void run () {
// TODO: Figure out how to get the splash screen
to be "topmost"
// Currently when the main window is
created, it will appear
// in front of the splash screen.
splash.setVisible (true);
// wait for the specified number of milliseconds
try { Thread.sleep (duration); } catch (Exception e) {}
// When the timer expires hide the window and get
rid of it
splash.setVisible (false);
splash = null;
}
};
r.start ();
}

public static void main (String [] args) {
showSplash (5000);
SqlManEditor s = new SqlManEditor ();
s.toBack (); // After these two lines of
code execute
splash.toFront (); // s is in front and splash
is still in back!
}
}
 
A

Alex Hunsley

Glenn said:
I am trying to create a splash screen. I would like it to be visible for a
few seconds while the application is initialising. After a timer expires,
the splash screen will close automatically. I have all of this working just
fine.

Hi there
just a few points, as I've tried to run your example but had a few problems.
If you post code, it helps if its complete. This includes:
1) including the correct imports
2) including all code needed to run the example - your code references a
SplashPanel class which isn't in your posted code.

Also, when writing java, it's a good idea to keep your lines within the
80 chars width limit. One of the downsides of not following this
guideline is that when you post wide code, your news posting software
may wrap the lines at 80 chars or similar, as it appears to have done in
this case. The end result is java code that has comments continuing onto
the next line, and the code won't compile without editing.

Post complete working code and I'll have a look at it!

alex
 
G

Glenn McCall

Post complete working code and I'll have a look at it!

No problem. I can't post the complete code but here is a cut down version
that does the same thing.
You might need to mess with the window sizes to get them to overlap and you
can see parts of both.
I tried to make it so that they would overlap in the center of the screen. I
also included some comments about some of the the things I have tried.

Just to restate the problem:
The splash screen always appears underneath the main window when it becomes
visible.



First the SplashPanel
//-------------------------------------------------------------
import javax.swing.*;
import java.awt.*;

public class SplashPanel extends JPanel {

public SplashPanel () {
setLayout (new BoxLayout (this, BoxLayout.Y_AXIS));

setBounds (0, 0, 240, 120);
add (new JLabel ("A really really really wide splash screen."));
add (new JLabel ("So wide so that it hopefully will show under " +
"the main window."));
add (new JLabel ("And a few JLabels so that it will have a " +
"little height"));

setBackground (Color.WHITE);
setOpaque (true);
}
}
//-------------------------------------------------------------

Next the SqlManEditor
//-------------------------------------------------------------
import javax.swing.*;
import java.awt.*;

public class SqlManEditor extends JFrame {

public SqlManEditor () {
// Simulates initialisation activity in main thread.
// Moving this activity to after the setVisible (true)
// doesn't help much either.
try { Thread.sleep (500); } catch (Exception e) {}

pack ();
// You may need to adjust this to get the splash screen to overlap
// the main window.
setSize (200, 300);
// Code borrowed from showSplash to try
// and force the two windows to overlap.
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize ();
int x = (screen.width - getWidth()) / 2;
int y = (screen.height - getHeight()) / 2;
setBounds (x, y, getWidth(), getHeight());

setVisible (true);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
// Putting the initialisation workload here after the setVisible (true)
// doesn't seem to help either.
}


private static JWindow splash;

private static void showSplash (final int duration) {
/* final JWindow */ splash = new JWindow ();
SplashPanel content = new SplashPanel ();

splash.setContentPane(content);
splash.pack ();

Dimension screen = Toolkit.getDefaultToolkit().getScreenSize ();
int x = (screen.width - content.getWidth()) / 2;
int y = (screen.height - content.getHeight()) / 2;
splash.setBounds (x, y, content.getWidth(), content.getHeight());


Thread r = new Thread () {
public void run () {
// TODO: Figure out how to get the splash screen to be "topmost"
// Currently when the main window is created, it will appear
// in front of the splash screen.
splash.setVisible (true);
// wait a little while
try { Thread.sleep (duration); } catch (Exception e) {}
splash.setVisible (false);
splash = null;
}
};
r.start ();
}


public static void main (String [] args) {
showSplash (5000);
SqlManEditor s = new SqlManEditor ();
s.toBack ();
splash.toFront ();
}
}

//-------------------------------------------------------------
 
A

Andrew Thompson

Glenn McCall said:
No problem. I can't post the complete code but here is a cut down version
that does the same thing.

Now we're cookin' with gas (is very good stuff)

Well, I was not able to solve the question of
why it did not work your way, but I have come
up with a rather 'hackish' fix that works for the
1.4.2 JVM on XP.

Maybe Alex or others wiil come up with
a better solution..
_______________________________________
import javax.swing.*;
import java.awt.*;

class SplashPanel extends JPanel {

public SplashPanel () {
setLayout (new BoxLayout (this, BoxLayout.Y_AXIS));

setBounds (0, 0, 240, 120);
add (new JLabel ("A really really really wide splash screen."));
add (new JLabel ("So wide so that it hopefully will show under " +
"the main window."));
add (new JLabel ("And a few JLabels so that it will have a " +
"little height"));

setBackground (Color.WHITE);
setOpaque (true);
}
}
/*-------------------------------------------------------------

Next the SqlManEditor
//-------------------------------------------------------------
*/

public class SqlManEditor extends JFrame {

public SqlManEditor () {
// Simulates initialisation activity in main thread.
// Moving this activity to after the setVisible (true)
// doesn't help much either.
try { Thread.sleep (500); } catch (Exception e) {}

pack ();
// You may need to adjust this to get the splash screen to overlap
// the main window.
setSize (200, 300);
// Code borrowed from showSplash to try
// and force the two windows to overlap.
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize ();
int x = (screen.width - getWidth()) / 2;
int y = (screen.height - getHeight()) / 2;
setBounds (x, y, getWidth(), getHeight());

setVisible (true);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
// splash.toFront ();
if ( splash.getFocusableWindowState() )
{
splash.requestFocus();
splash.hide();
splash.show();
// splash.toFront ();
System.out.println("Window to front!");
}
else System.out.println("Window is not focusable!");
// Putting the initialisation workload here after the setVisible (true)
// doesn't seem to help either.
}


private static JWindow splash;

private static void showSplash (final int duration) {
/* final JWindow */ splash = new JWindow ();
SplashPanel content = new SplashPanel ();

splash.setContentPane(content);
splash.pack ();

Dimension screen = Toolkit.getDefaultToolkit().getScreenSize ();
int x = (screen.width - content.getWidth()) / 2;
int y = (screen.height - content.getHeight()) / 2;
splash.setBounds (x, y, content.getWidth(), content.getHeight());


Thread r = new Thread () {
public void run () {
// TODO: Figure out how to get the splash screen to be "topmost"
// Currently when the main window is created, it will appear
// in front of the splash screen.
splash.setVisible (true);
// wait a little while
try { Thread.sleep (duration); } catch (Exception e) {}
splash.setVisible (false);
splash = null;
}
};
r.start ();
}


public static void main (String [] args) {
showSplash (10000);
SqlManEditor s = new SqlManEditor ();
// s.toBack ();
}
}
___________________________________

HTH
 
A

Adam

Glenn McCall said:
I am trying to create a splash screen. I would like it to be visible for a
few seconds while the application is initialising. After a timer expires,
the splash screen will close automatically. I have all of this working just
fine.

However, at some point during the application initialisation, it creates the
main window. When this occurs, the main window appears on top of the splash
screen.

Don't put 'show()' or 'setVisible(true)' in the constructor of your main
window.

The way I see it:
in main thread you should:
1.) create the splash screen and show it
2.) call a blocking method that will init your app,
that means creating the main window, but not
showing it.
3.) when all init is completed you get rid of the splash
screen and show the main window.

As simple as that. If you want your splash screen
to be visible longer than point 2.) duration,
you can just put sleep() right before point 3.)

Adam
 
A

antroy

Glenn said:
I am trying to create a splash screen. I would like it to be visible for a
few seconds while the application is initialising. After a timer expires,
the splash screen will close automatically. I have all of this working just
fine.

However, at some point during the application initialisation, it creates the
main window. When this occurs, the main window appears on top of the splash
screen. I would prefer that the splash screen be "top most" when this
occurs.

Why not wait until all initialization is complete before calling
setVisible(true) on the main window? This is the usual way that splash
screens work.

Your method seems a bit strange - having the splashscreen timed to a
fixed duration. In my apps, the splashscreen is the first thing created
and displayed. I then initialize all components in the main window,
followed by the lines:

splash.setVisible(false);
main.setVisible(true);

How do you choose the duration of the timer? Surely it is not a reliable
way of getting the splash screen to disappear as the main window appears.
 
G

Glenn McCall

Good questions.

The idea stems from a couple of other applications I use. Probably the most
common is paintshop pro. Where the splash screen remains displayed for a
minimum number of seconds or until the user clicks on it. Or the user can
simply start working in PaintShop Pro ignoring the splash screen.

To me (and this is just my opinion so you don't have to agree), the splash
screen is a number of things. It is a promotional thing, it is an
introductory/welcoming thing, it provides information and shows that the
application is on its way.

Sometimes like paintshop pro, the application initialises in about 1/2 a
second which is way to short a time to actually "see" the splash screen. If
Paintshop used the main.show (); splash.hide () approach, the splash screen
would be more like a flash screen. This would be true for my app as well.
However, there might be times when initialisation will take longer (eg.
depending upon the users configuration, I might establish some database
connections. For another user, this might not be necessary). So like paint
shop pro, I wanted to create an environment where the splash screen was
displayed for a minimum period of time, or until the user dismisses it or
the main window appears.

In terms of your specific question about the timer, the code I supplied here
is the starting point. If I can solve the problem of getting the splash
screen in front, then I will add functionality to close it if the user
clicks on it. Also, I will add functionality so that after the timer
expires, it will check to see if the main window is visible. If it is, then
the splash will close, otherwise it will remain visible until the main
window becomes visible - at that point it will close.

If I may be so presumptious to replace your word "strange" with "different",
I would then say it is our differences that make us unique (and hopefully
interesting).
 
G

Glenn McCall

Firstly, the replies to my original post have been very interesting, but
they prompted me to think of this question in a different way?

Suppose I had a drawing program and I needed to have a toolbox of icons that
I could drag and drop onto the drawing area. How can I get the toolbox
window to "float" above the drawing area so that it is always visible? And
can that approach be used for the splash screen as well?
 
J

Jason Teagle

Firstly, the replies to my original post have been very interesting, but
they prompted me to think of this question in a different way?

Suppose I had a drawing program and I needed to have a toolbox of icons that
I could drag and drop onto the drawing area. How can I get the toolbox
window to "float" above the drawing area so that it is always visible? And
can that approach be used for the splash screen as well?

If the floating panel is OK to be constrained within the main frame of the
drawing app, then you can achieve that by drawing the toolbox on the glass
pane that always sits at the front of the frame (when enabled). Perhaps this
technique could also be used for the splash screen - you just have to make
the frame big enough to contain it.

In fact, why not simply build the splash screen as the only child of the
frame's content pane to begin with, and then remove it and build the proper
frame contents when your initial actions are complete / timer finishes?
 
D

Derek Clarkson

Hi,
I would suggest that having a timed splash screen is not a good idea. I know
that there are a number of products which do this, but I consider it to be
generally not good. The reasons is that quite often a user is starting an
application in order to do something specific. I.e. it might be started in
response to an association on a file or the user might want to quickly
start it, modify a piece of information and then exit. These sorts of
situations are where users get frustrated with applications which take a
long time to start.

Having a splash screen which is sitting in front of them and not assisting
in what they are doing is only going to increase any such annoyance.
Especially if they can see that the application is up and ready behind it
and they can't get to it.

You can add a "close" button to the splash screen but then you are asking
users to perform an additional task in order to use your application. Again
they won't like it.

cruft like splash screens is a great way to make an application look
"pretty", but if they get in the way of the user in any way shape or form,
then you run the risk of the user going somewhere else. Remember, the main
job of any application is to perform a task for the user. Cruft should
never get in the way of this.

If your not convinced by these thoughts, I would suggest you doing some
ready on programs and user interaction. An especially good one that came
out recently was Eric S Raymonds "the Art of Unix Programming" which
highlights a lot of issues in regard to well behaved programs.
 
A

Andrew Thompson

Glenn McCall said:
Good questions.

What questions?

Please do not top-post. It makes
conversations difficult to follow
In terms of your specific question about the timer, the code I supplied here
is the starting point. If I can solve the problem of getting the splash
screen in front, then I will add functionality to close it if the user
clicks on it.

Did my solution not work for you?

It worked fine in the 1.4.2 JVM on XP.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top