I have a SplashScreen class which displays a image and a progress bar until some databases are initialized. I want that after the splashscreen ends a new window is opened. I have the following code:
public class Gui{
private static final String IMG_PATH = "../opt/images/splashscreendef.jpg";
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Gui ui = new Gui();
}
});
}
private inTouchGui() {
InitSplashScreen splash = null;
splash = new InitSplashScreen();
try {
splash.initUI();
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
BufferedImage img = null;
try {
img = ImageIO.read(new File(IMG_PATH));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ImageIcon icon = new ImageIcon(img);
JLabel label = new JLabel(icon);
JOptionPane.showMessageDialog(null, label);
}
}
public class InitSplashScreen {
private JDialog dialog;
private JProgressBar progress;
public void initUI() throws MalformedURLException {
showSplashScreen();
SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>(){
@Override
protected Void doInBackground() throws Exception {
Thread thread = new Thread(new InitProcess());
thread.start();
int i = 0;
while (thread.isAlive()){
i++;
Thread.sleep(200);// Loading of databases
publish(i);// Notify progress
}
if (i < 10){
for (i = 0; i < 100; i++){
Thread.sleep(50);// We simulate loading even if database is fully loaded
publish(i);// Notify progress
}
}
return null;
}
@Override
protected void process(List<Integer> chunks) {
progress.setValue(chunks.get(chunks.size() - 1));
}
@Override
protected void done() {
hideSplashScreen();
}
};
worker.execute();
}
protected void hideSplashScreen() {
dialog.setVisible(false);
dialog.dispose();
}
protected void showSplashScreen() throws MalformedURLException {
dialog = new JDialog((Frame) null);
dialog.setModal(false);
dialog.setUndecorated(true);
JLabel background = new JLabel(new ImageIcon("splashscreendef.jpg"));
background.setLayout(new BorderLayout());
dialog.add(background);
progress = new JProgressBar();
background.add(progress, BorderLayout.SOUTH);
dialog.pack();
dialog.setLocationRelativeTo(null);
dialog.setVisible(true);
}
}
When I run the code I get at the same time both the splash screen and the image window, I have tried to use worker.get()
but then nothing appears in screen. Could you give me some advice? I am pretty new to Java Swing.
By the way, would it be possible (with possible meaning not a insane load of code and hours to make it work) to implement a login window like this one, for example?
http://designsparkle.com/wp-content/uploads/2014/06/a-simple-html-css-login-for.jpg
Thanks in advice.
Change your way of thinking
Initialise and show the splash screen, when it's finished, initialise and show the Gui
This will require to have some way to tell who ever initialised the splash screen that it has completed, to do this, you can use a PropertyChangeListener
...
public class InitSplashScreen {
//...
public void initUI(PropertyChangeListener listener) throws MalformedURLException {
showSplashScreen();
SwingWorker<Void, Integer> worker = new SwingWorker<Void, Integer>() {
//...
};
worker.addPropertyChangeListener(listener);
worker.execute();
}
Then you listen for the state
change property and check the state of the work...
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
InitSplashScreen splashScreen = new InitSplashScreen();
try {
splashScreen.initUI(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String name = evt.getPropertyName();
if ("state".equalsIgnoreCase(name)) {
SwingWorker worker = (SwingWorker) evt.getSource();
if (worker.getState().equals(SwingWorker.StateValue.DONE)) {
Gui ui = new Gui();
}
}
}
});
} catch (MalformedURLException ex) {
ex.printStackTrace();
}
}
});
}
But remember, you need to remove the splash screen from the Gui
code.
You can also use this to "get" any information from the SwingWorker
that the Gui
might need and pass it as a parameter to the constructor or via setters depending on your needs
Also, to me, this...
Thread thread = new Thread(new InitProcess());
thread.start();
Looks like a strange thing to do within a SwingWoker
. You could simply leave the JProgressBar
in indeterminate mode if you don't know how much work is required