Search code examples
javaimageswingsplash-screengraphics2d

Grey splash screen due to no repainting


I'm making a splash screen for my application. It's just static BufferedImage drawn by Graphics2D, inside JFrame with no decorations. My problem is: the window sometimes isn't drawn properly, it means it doesn't always contain my image, it's sometimes just grey. I tried already creating splash screen in second thread, but it didn't help. I could call splashScreen.repaint() every line, but it's nonsense... Here's my code:

package SeriousSteve.MapEditor;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;

/**
 * Simple splash screen, contains only the image.
 * 
 * @author m4tx3
 */
public class SplashScreen extends JFrame {

    private BufferedImage image;

    /**
     * Constructor. Creates a window with splash screen, loads an image at the
     * URL specified in imageURL, and finally displays this image.
     * 
     * @param imageURL  URL to the image that you want to put on the splash
     *                  screen.
     */
    public SplashScreen() {
        super("Splash screen");
    }

    public void createSplashScreen(final URL imageURL) {
        try {
            image = ImageIO.read(imageURL);
        } catch (IOException ex) {
            Logger.getLogger(SplashScreen.class.getName()).
                    log(Level.SEVERE, null, ex);
        }
        setUndecorated(true);
        setSize(image.getWidth(), image.getHeight());
        setLocationRelativeTo(null);
        setVisible(true);

        createGraphics();

        repaint();
    }

    /**
     * Creates a graphics context and draws a splash screen.
     */
    private void createGraphics() {
        Graphics2D g = (Graphics2D) getGraphics();
        g.drawImage(image, 0, 0, null);
    }

    /**
     * Closes the splash screen and frees the memory taken by the image.
     * 
     * Call this function when the loading is complete.
     */
    public void close() {
        setVisible(false);
        image = null;
        dispose();
    }
}

And:

    SplashScreen splashScreen = new SplashScreen();
    splashScreen.createSplashScreen(getClass().getResource(
            "Img/splash.png"));

Btw., - I'm creating my own splash screen class, because I've got 2 apps (the game and map editor for it) in 1 jar... I want to show splash screen only in map editor, so I can't modify manifest file.

Regards


Solution

  • Use a JLabel instead. Painting on the frame directly is a bad idea.

    See this, it works everytime:

    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    import javax.imageio.ImageIO;
    import javax.swing.ImageIcon;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.SwingUtilities;
    
    /**
     * Simple splash screen, contains only the image.
     * 
     * @author m4tx3
     */
    public class SplashScreen extends JFrame {
    
        /**
         * Constructor. Creates a window with splash screen, loads an image at the URL specified in imageURL, and finally displays this image.
         * 
         * @param imageURL
         *            URL to the image that you want to put on the splash screen.
         */
        public SplashScreen() {
            super("Splash screen");
        }
    
        public void createSplashScreen(final URL imageURL) {
    
            JLabel splashLabel = new JLabel(new ImageIcon(imageURL));
            add(splashLabel);
                setSize(splashLabel.getPreferredSize());
            setUndecorated(true);
            setLocationRelativeTo(null);
            setVisible(true);
    
            repaint();
        }
    
        /**
         * Closes the splash screen and frees the memory taken by the image.
         * 
         * Call this function when the loading is complete.
         */
        public void close() {
            setVisible(false);
            dispose();
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    try {
                        new SplashScreen().createSplashScreen(new URL(
                                "http://art.gnome.org/download/themes/splash_screens/1334/Splash-GnomeDarkSplashScreen.png"));
                    } catch (MalformedURLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            });
        }
    }