0

I have kind of a problem with showing loader during a heavy data loading by main program. Below there is a class called SplashScreen which displays .gif animation of loader.

public class SplashScreen extends JWindow {

public SplashScreen() {
    super();
    Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resources/load.gif"));
    try {
        if (image != null) {
            JLabel imageLabel = new JLabel();
            imageLabel.setIcon(new ImageIcon(image));
            this.getContentPane().setLayout(new BorderLayout());
            this.getContentPane().add(imageLabel, BorderLayout.CENTER);
            this.pack();
            Dimension screenSize =
                    Toolkit.getDefaultToolkit().getScreenSize();
            Dimension labelSize = imageLabel.getPreferredSize();
            setLocation(screenSize.width / 2 - (labelSize.width / 2),
                    screenSize.height / 2 - (labelSize.height / 2));
            addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    dispose();
                }
            });
            addKeyListener(new KeyAdapter() {
                public void keyTyped(KeyEvent e) {
                    dispose();
                }
            });
        }
    } catch (Exception ex) {
    }
}

There is a result of running this piece of code :

Loader gif

But when I would like to load a lot of data (say 1 milion records) I have something like this :

Loader gif blank

I was using Thread, EventQueue.invokeLater and SwingUtilities to show SplashScreen in separate Thread, but it doesn't work. It is always blank when I load heavy data. Unfortunately, I must say that using EventQueue or SwingUtilities is quite difficult, because of you are not able to end tasks started by those utilities.

Lukasz Ciesluk
  • 718
  • 1
  • 17
  • 29
  • 3
    invokeLater will execute the runnable, at some time in the future, with the context of the EDT, that's the point. Instead, try running your blocking code in a SwingWorker instead – MadProgrammer Feb 03 '15 at 08:56
  • 2
    For [example](http://stackoverflow.com/a/25526869/230513). – trashgod Feb 03 '15 at 11:11

1 Answers1

1

I finally figured out how to properly implement this case.

1) Implement SplashScreen which will display loader (.gif)

    public class SplashScreen extends JWindow {

        public SplashScreen() {
            super();
            Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/resources/load.gif"));
            try {
                if (image != null) {
                    JLabel imageLabel = new JLabel();
                    imageLabel.setIcon(new ImageIcon(image));
                    this.getContentPane().setLayout(new BorderLayout());
                    this.getContentPane().add(imageLabel, BorderLayout.CENTER);
                    this.pack();
                    Dimension screenSize =
                            Toolkit.getDefaultToolkit().getScreenSize();
                    Dimension labelSize = imageLabel.getPreferredSize();
                    setLocation(screenSize.width / 2 - (labelSize.width / 2),
                            screenSize.height / 2 - (labelSize.height / 2));
                    addMouseListener(new MouseAdapter() {
                        public void mouseClicked(MouseEvent e) {
                            dispose();
                        }
                    });
                    addKeyListener(new KeyAdapter() {
                        public void keyTyped(KeyEvent e) {
                            dispose();
                        }
                    });
                }
            } catch (Exception ex) {
            }
        }

        @Override
        public void dispose() {
            setVisible(false);
        }
}

2) Init ScheduledExecutorService

ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

3) Implement Thread responsible for showing SplashScreen

Thread splashThread = new Thread(new Runnable() {
            public void run() {
                setSplashScreen(new SplashScreen());
                getSplashScreen().setVisible(true);
                getSplashScreen().toFront();
                getSplashScreen().setAlwaysOnTop(true);
            }
        });

4) Schedule new created Thread

executor.schedule(splashThread, 0, TimeUnit.MILLISECONDS);

5) When there is a need to dispose SplashScreen

getSplashScreen().dispose();

Additionally you can create separate Thread to check if there is a need to dispose SplashScreen.

private void invokeExecutor() {
    executor.scheduleAtFixedRate(new DoneTask(), 0, 200, TimeUnit.MILLISECONDS);
}

private class DoneTask implements Runnable {
    @Override
    public void run() {
        if (fileWorker.isDone()) { //SwingWorker
            getSplashScreen().dispose();
        }
    }
}
Lukasz Ciesluk
  • 718
  • 1
  • 17
  • 29