Animierter Splash Screen

Hi,

jede halbwegs reale Application hat heutzutage einen Splashscreen. Ich habe heute nacht mal einen Splashscreen geschrieben der sich einblendet und wieder ausblendet. Hierbei kann man die Zeit die benötigt wird angeben. Das ganze ist bis jetzt nur auf einem Desktop mit 32 Bit farbtiefe getestet, sollte unter Linux (meist nur 24 bit) etc aber laufen denke ich. Evtl hat ja jemand daran interresse. Ich habe das ganze mit einem .png bild getestet, jedes andere bildformat sollte ebenfalls funktionieren, aber gerade png’s oder gif bilder sind interresant da der desktop hintergrund weiterhin durchscheint.

Die Klasse SplashScreen braucht im Konstruktor einfach den relativen pfad zu dem Bild welches eingeblendet werden soll. Bei mir hier liegt das bild im resourcen verzeichniss unter „de/nicedezigns/musicbox/gui/resources/logo_big.png“.

Für das eigendliche zeichnen des Splashscreen benutze ich einfach ein JLabel welches das aktuelle Bild kennt und dieses zeichnet. bei der übergabe des Bildes an das JLabel wird auch immer dessen grösse gesetzt sonst würde man das JLabel nicht sehen da es sonst eine grösse von 0,0 pixeln hätte was eher schlecht wäre :wink:

Falls ihr das ganze nutzen wollt solltet ihr es folgendermassen anwenden:

```	public MeineApplication()
	{
		SplashScreen splashScreen = null;
	
		try
		{
			splashScreen = new SplashScreen("de/nicedezigns/musicbox/gui/resources/logo_big.png");			
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}

	  // hier startet ihr eure Application
	  doSomething();
	  // Die Application ist bereit zum anzeigen, also Splashscreen ausblenden
	  splashScreen.blendOut();
	  // Zeige Application
	  setVisible(true);

	}```

…hier aus eclipse herausgestartet sieht man den Editor durscheinen.

Anbei die beiden Klassen die ihr braucht:


import java.awt.AWTException;
import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JWindow;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

/**
 * <p>
 * Title: SplashScreen
 * </p>
 * <p>
 * Description: Animated Splashscreen
 * </p>
 * <p>
 * Copyright: Copyright (c) 2006
 * </p>
 * <p>
 * Company: Nice Dezigns
 * </p>
 * 
 * @author Jens Hohl
 * @date 05.08.2006
 * @time 01:14:25
 */
public class SplashScreen implements ActionListener
{
	// desktop
	private final BufferedImage background;

	// Your logo
	private final BufferedImage image;

	// actual image
	private BufferedImage currentImage;

	private SplashPainter label;

	private final int speed = 1000 / 20;

	/**
	 * Duration in Time Mills
	 */
	private float duration = 3000.0f;

	private long startTime = 0;

	private boolean isBlendIn = true;

	private final Timer timer;

	public SplashScreen(String path) throws IOException, AWTException
	{
		final URL url = this.getClass().getClassLoader().getResource(path);
		image = ImageIO.read(url);

		currentImage = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage(image.getWidth(null), image.getHeight(null));

		final Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
		final int x = (int) (screenDimension.getWidth() / 2 - image.getWidth(null) / 2);
		final int y = (int) (screenDimension.getHeight() / 2 - image.getHeight(null) / 2);
		final int w = image.getWidth(null);
		final int h = image.getHeight(null);

		final Robot robot = new Robot();
		final Rectangle rectangle = new Rectangle(x, y, w, h);
		background = robot.createScreenCapture(rectangle);
		drawImage(0f);

		label = new SplashPainter();
		label.setImage(background);
		final JWindow f = new JWindow(new JFrame());
		f.getContentPane().add(label);
		f.pack();
		f.setLocationRelativeTo(null);

		timer = new Timer(speed, this);
		timer.setCoalesce(true);
		timer.start();
		startTime = System.currentTimeMillis();
		f.setVisible(true);
	}

	public void blendOut()
	{
		isBlendIn = false;
		startTime = System.currentTimeMillis();
		timer.start();
	}

	public void actionPerformed(ActionEvent e)
	{
		float percent;

		if (isBlendIn)
		{
			percent = (System.currentTimeMillis() - startTime) / duration;
			percent = Math.min(1.0f, percent);
		}
		else
		{
			percent = (System.currentTimeMillis() - startTime) / duration;
			percent = Math.min(1.0f, percent);
			percent = 1.0f - percent;
		}

		float alphaValue = percent;

		if (percent >= 1.0)
		{
			timer.stop();
			// blendOut(); // Einkommentieren damit die animation sofort wieder
			// ausgeblendet wird
		}
		else if (alphaValue <= 0.0f)
		{
			timer.stop();
			SwingUtilities.getWindowAncestor(label).dispose();
		}

		drawImage(alphaValue);
		label.setImage(currentImage);
		label.repaint();
	}

	/**
	 * Draws Background, then draws image over it
	 * 
	 * @param alphaValue
	 */
	private void drawImage(float alphaValue)
	{
		final Graphics2D g2d = (Graphics2D) currentImage.getGraphics();
		g2d.drawImage(background, 0, 0, null);
		g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alphaValue));
		g2d.drawImage(image, 0, 0, null);
		g2d.dispose();
	}

	public static void main(String[] args) throws Exception
	{
		new SplashScreen("de/nicedezigns/musicbox/gui/resources/logo_big.png");
	}
}

Und das JLabel:


import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;

import javax.swing.JLabel;

/**
 * <p>
 * Title: SplashPainter
 * </p>
 * <p>
 * Description: Displays Spashimage 
 * </p>
 * <p>
 * Copyright: Copyright (c) 2006
 * </p>
 * <p>
 * Company: Nice Dezigns
 * </p>
 * 
 * @author Jens Hohl
 * @date 05.08.2006
 * @time 03:36:39
 */
public class SplashPainter
	extends JLabel
{
	private Image image;
	
	public void setImage(Image image)
	{
		this.image = image;
		setPreferredSize(new Dimension(image.getWidth(null),image.getHeight(null)));
	}
	
	@Override
	public void paintComponent(Graphics g)
	{
		super.paintComponents(g);
		g.drawImage(image,0,0,this);
	}
}




Den code könnt ihr frei verwenden, ohne anspruch auf korrektheit. Verbesserungsvorschläge sind jederzeit willkommen. :smiley:

mfg,
Jens

Wenn wir schon dabei sind: Ich hab sowas auch schon geschrieben :wink:

package de.illu.swing;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferStrategy;
import java.util.Hashtable;
import java.util.Set;

import javax.swing.JFrame;

import de.illu.util.Util;

/**
 * @author Illuvatar
 */
public class Splashscreen extends JFrame
{
    /**
     * Diese Variable wird von Java5 verlangt.
     */
    public static final long serialVersionUID = 159372468L;
    private short alpha;
    private Image img;
    private Image bg;
    private BufferStrategy strategy;
    private Rectangle rect;
    private Hashtable<String, String> info;
    private boolean fadeinfo;

    /**
     * Constructor
     * 
     * @param img
     *            Das Image, das in dem Splashscreen gezeichnet werden soll
     * @param alpha
     *            Der alpha-Wert (0 = durchsichtig, 255 = undurchsichtig)
     * @param inFade
     *            Die Zeit zum einfaden in Millisekunden
     * @param title
     *            Der Titel, der in der Taskleiste erscheint
     * @param info
     *            Key/Value - Paare, die als zusätzliche Information unten in
     *            den Splashscreen geschrieben werden. Kann null sein.
     * @param fadeinfo
     *            Soll diese Info mitgefadet werden?
     */
    public Splashscreen(Image img, short alpha, long inFade, String title,
            Hashtable<String, String> info, boolean fadeinfo)
    {
        super(title);
        this.alpha = alpha;
        this.img = img;
        this.info = info;
        this.fadeinfo = fadeinfo;
        setSize(img.getWidth(this), img.getHeight(this));
        setLocationRelativeTo(null);
        rect = getBounds();
        try {
            Robot robot = Swingutil.createDefaultRobot();
            bg = robot.createScreenCapture(rect);
        } catch (AWTException e) {
            e.printStackTrace();
        }
        setUndecorated(true);
        setAlwaysOnTop(true);
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        setIgnoreRepaint(true);
        setResizable(false);
        addComponentListener(new ComponentAdapter() {
            public void componentMoved(ComponentEvent evt)
            {
                setLocationRelativeTo(null);
            }
        });
        addWindowListener(new WindowAdapter() {
            public void windowIconified(WindowEvent evt)
            {
                setState(Frame.NORMAL);
            }
        });
        setVisible(true);
        getGraphics().drawImage(bg, 0, 0, this);
        createBufferStrategy(2);
        strategy = getBufferStrategy();
        setIgnoreRepaint(false);
        if (inFade > 0) {
            setIgnoreRepaint(true);
            long start = System.currentTimeMillis();
            long now;
            loop: while (true) {
                now = System.currentTimeMillis();
                if ((now - start) >= inFade) {
                    break loop;
                }
                this.alpha = (short) ((((double) (now - start)) / inFade) * alpha);
                paint(getGraphics());
                Util.sleep(7); // Performance
            }
            this.alpha = alpha;
            setIgnoreRepaint(false);
            repaint();
        }
    }

    /**
     * Die Methode wird zum Zeichnen des Fensters verwendet.
     */
    public void paint(Graphics gr)
    {
        Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
        g.clearRect(rect.x, rect.y, rect.width, rect.height);
        g.drawImage(bg, 0, 0, this);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
                alpha / 255.0F));
        g.drawImage(img, 0, 0, this);
        if (info != null) {
            if (!fadeinfo)
                g.setComposite(AlphaComposite.getInstance(
                        AlphaComposite.SRC_OVER, 1));
            Font f = new Font("Serif", Font.BOLD, 16);
            g.setFont(f);
            Set<String> s = info.keySet();
            int height = getSize().height;
            int halfwidth = getSize().width / 2;
            for (String key : s) {
                height -= (f.getSize() + 4);
                String value = info.get(key);
                g.drawString(key, halfwidth
                        - 4
                        - (int) (f.getStringBounds(key, g
                                .getFontRenderContext()).getWidth()), height);
                g.drawString(value, halfwidth + 4, height);
            }
        }
        g.dispose();
        strategy.show();
    }

    /**
     * Fadet den Splashscreen aus, und macht ihn invisible.
     * 
     * @param time
     *            Die Zeit zum Ausfaden
     * @param captureNew
     *            Gibt an, ob ein neues Bild gemacht werden soll.<br/><b>Achtung:</b>
     *            Wenn der Wert true ist, wird das Fenster kurz flackern, um dem
     *            Robot die "Sicht" auf das dahinterliegende zu geben.
     */
    public void fadeOut(long time, boolean captureNew)
    {
        if (captureNew)
            try {
                Robot robot = Swingutil.createDefaultRobot();
                setVisible(false);
                bg = robot.createScreenCapture(rect);
            } catch (AWTException e) {
                e.printStackTrace();
            }
        setVisible(true);
        short alpha = this.alpha;
        setIgnoreRepaint(true);
        long start = System.currentTimeMillis();
        long now;
        loop: while (true) {
            now = System.currentTimeMillis();
            if ((now - start) >= time) {
                break loop;
            }
            this.alpha = (short) ((((double) (time - (now - start))) / time) * alpha);
            paint(getGraphics());
            Util.sleep(7); // Performance
        }
        this.alpha = alpha;
        setVisible(false);
    }
}

Verwendung:

Splashscreen ss = new Splashscreen (someImage, (short)255, 2000, "Splash", null, false);
//doSth
ss.fadeOut(1000, false);

Wo ich das anschau: Ein-zwei Sachen sind etwas unschön im Code. Aber er ist auch schon älter :wink:

Vielleicht wäre das noch ganz geil wenn man das hinkriegen würde das der Screen solange angezeigt wird bis das Programm wirklich geladen ist?!
So eine Art MediaTracker.

Ich gehe davon aus das wenn du in deinem Programm setVisible(true) aufrufst es geladen ist :wink:

Indem fall einfach die methode blendOut(); aufrufen und der splash verschwindet…

-jens

Ich habe keine Frage, ich möchte nur hier eine Linux-Distribution empfehlen.

Für Leute die Linux kennenlernen möchte oder ganz umsteigen wollen, empfehle ich Ubuntu. Diese Linux-Distribution ist sehr benutzerfreundlich, für Anfänger aber auch für Fortgeschrittenen Linux Benutzer ideal geeignet und die Forum Comunity ist herrvoragend. Ich war auch ein Anfänger, der noch nie Linux gesehen hat und habe Ubuntu sehr schnell verstanden.

Hier Link zu diesem Betriebsystem: Ubuntu

weiß nicht genau ich hatte mit Suse angefangen um son bisschen Grundlagen zu bekommen und bin derzeit bei Debian gelandet werd aber wohl bald auch mal Ubuntu testen

Ich fahre seit einigen Wochen Ubuntu. Bin damit ausserordentlich zufrieden!
Vorher war ich bei Debian angefangen habe ich mit Mandrake (jetzt Mandrive).
Ubuntu ist wirklich einen tolle Distribution, die wie ich finde nicht überladen wirkt und keinem Neuling Angst macht. Deweiteren baut Ubuntu auf Debian auf und Apt ist mit dabei :slight_smile: Die Hardwareerkennung ist meiner Meinung nach hervorragend was wieder für Ubuntu spricht. Die Community ist riesig, was bei anderen Distributionen nicht weniger sein dürfte :slight_smile: Auch im Chat wird man nicht als Dummbeutel dargestellt nur weil man Anfänger ist. Auch bei kleinen Problemen wird einem dort promt und zuverlässig geholfen.

mal probieren… Freespire 1.0 klingt auch recht gut…http://www.freespire.org/

Ich habe auf meinem Zweitrechner auch Ubuntu drauf. Es ist die Linux-Distribution, die bisher am längsten auf meiner Platte überlebt hat.

Grund: Einerseits hat mir bullzeye unheimlich viel dabei geholfen, das System in Gang zu bekommen (einige Dinge gehen immer noch nicht), andererseits ist diese Distribution sehr sparsam, was die im System zur Anwendung bereitsgestellte Software betrifft. Das macht das System für den Einsteiger recht übersichtlich und man kann sich zunächst mal auf die neue Umgebung “einschießen”, statt gleich von einer Unmenge an Installations- und Konfigurationsproblemen den Appetit auf mehr nehmen zu lassen.

gentoo

weil wenn mal was nicht geht, hat man ein system was darauf ausgerichtet ist, das man an alles rankommt und auf auf dieser ebene noch ausreichend doku zur verfügung steht. da fand ich mich gerade bei ubuntu etwas alleine gelassen, vielleicht habe ich aber auch die doku garnicht wirklich gefunden. Die off. seite war jedenfalls recht dünne und imho sind die gentoo.foren auch deutlich größer.

ausserdem gefällt mir das konzept von source-based-distributionen besser als binärpakete zu verteilen…

Hehe, ich muss mich der Mehrheit anschliessen: Kubuntu. Nachdem meine Festplatte im Eimer war, und Windows nichtmal neu installiert werden konnte (Den Pinguin lies das alles kalt), bin ich treuer Benutzer von Linux :smiley:

ubuntu ist absolut super für einsteiger, aber gentoo übertrifft alles. ich hatte noch nie eine so aktuelle distri(2-3 tage nach erscheinen der firefox-beta2 gab es die schon in portage) und gleichzeitig stabil und schnell. aber für einsteiger ist gentoo meiner meinung nach absolut nichts, da man immer wieder vor probleme gestellt wird, die man durch schreiben in configs lösen muss. ich denke für einsteiger ist das nur abschreckend.
suse finde ich grausam. dort gibt es so viele pakete, die man nie gebraucht. dadurch wird das system viel zu langsam. im endeffekt empfinde ich suse als windows auf linuxbasis.

naja, in anderen distributionen wirst du mit demselben problem halt komplett alleine gelassen. soalnge man keinen mist anstellt und sich ein bißchen einliest ist gentoo überhaupt kein problem. von anfängerfreundlichkeit durch einfachheit halte ich wenig.

Hab auch Ubuntu … nach mehreren Problemen mit verschiedenen Distributionen (Suse hat ständig irgendwelche Fehler gebracht, Ubuntu lies sich zuerst nicht richtig auf meinem Laptop installieren, Mandriva lässt es bis heute nicht, …) binsch dann auch dort gelandet. Hab das mittlerweile bestimmt schon 4 Wochen und bin hoch zufrieden. Allerdings bin ich immernoch in der Lernphase und kann daher noch nicht sehr viel über die Vor- und Nachteile gegenüber anderen Distris sagen.