Splash Screen

bjmicha

Mitglied
Hallo,

ich würde gerne für meine Anwendung eine Art Splash Screen machen. Ich will einfach bevor das Programm gestartet wird 3 sekunden lang oder so ein image anzeigen lassen.
Ich brauche also keine komplizierten Klassen die den Splash Screen so lange anzeigen bis die Anwendung geladen ist oder so. Es geht einfach nur darum 3 sekunden lang ein image anzuzeigen.

Gruß

Michael
 
Mal eben quick'n'dirty:
Code:
// SplashScreen.java

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

import javax.swing.JWindow;

public class SplashScreen extends JWindow implements Runnable
{
	public void run()
	{
		setSize(400, 110);
		setLocationRelativeTo(null);
		setVisible(true);
		
		try
		{
			Thread.sleep(3000);
		}
		catch (InterruptedException e)
		{
			dispose();
		}
		dispose();	
	}
	
	public void paint(Graphics g)
	{
		Image splashImage = getToolkit().getImage("h:/h-ff-dl.png");
		g.drawImage(splashImage, 0, 0, this); 
	}
}
Das ist der eigentliche SplashScreen. Lässt sich natürlich noch verbessern. Gestartet wird dieser dann z.B. am Anfang deiner Hauptklasse über:
Code:
Thread splashThread = new Thread(new SplashScreen());
splashThread.start();
 
Hi!

Code:
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

/*
 * Created on 20.02.2004
 *
 * To change the template for this generated file go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */

/**
 * @author Darimont
 *
 * To change the template for this generated type comment go to
 * Window>Preferences>Java>Code Generation>Code and Comments
 */
public class SplashScreen extends JFrame {

	private Image img;
	private int x, y;

	private Timer timer;

	public SplashScreen(File pic, int x, int y, long millis) {

		this.x = x;
		this.y = y;
		setSize(x, y);

		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();

		setLocation(d.width / 2 - x / 2, d.height / 2 - y / 2);

		this.setUndecorated(true);

		MediaTracker mt = new MediaTracker(this);
		try {

			img = ImageIO.read(pic).getScaledInstance(x, y, Image.SCALE_SMOOTH);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			//e.printStackTrace();
			System.err.println("Konnte Datei nicht öffnen!");
		}
		setVisible(true);

		if (img == null)
			img = this.createImage(x, y);

		
		mt.addImage(img, 0);

		try {
			mt.waitForAll();
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		timer = new Timer();
		timer.schedule(new ExitSplashTask(this), millis);
		
	}

	public static void main(String[] args) {
		// Zeig mir das Bild c:\energy.jpg in der Größe 240,180, für 5 Sekunden an.
		SplashScreen screen =
			new SplashScreen(new File("c:/energy.jpg"), 240, 180, 5000);
	}

	public void paint(Graphics g) {
		super.paint(g);
		if (img != null)
			g.drawImage(img, 0, 0, this);
	}

	class ExitSplashTask extends TimerTask {

		private JFrame frm;

		public ExitSplashTask(JFrame frm) {
			this.frm = frm;
		}
		/* (non-Javadoc)
		 * @see java.util.TimerTask#run()
		 */
		public void run() {
			// TODO Auto-generated method stub
			frm.setVisible(false);
			frm.dispose();
			/* 
			 * Dieser Aufruf beendet hier die VM!
			 * Hier würde also normalerweise entweder die Klasse des Hauptprogramms
			 * 
			 */
			System.exit(0);
		}

	}
}

Gruß Tom
 
Zuletzt bearbeitet:
Hallo Fluke,

vielen dank.....
es klappt soweit nur das ich nicht weiss wie ich dir paint methode aufrufen soll
Was muss ich machend damit das bild auch angezeigt wird Was muss ich genau der paint methode als Graphics objekt übergeben?

Tausend Dank

Michael
 
Bei meiner wie gesagt schnellen und im Prinzip recht unsauberen Lösung, ersetzt du einfach "h:/h-ff-dl.png" durch den Dateinamen deines Bildes und passt setSize(400, 110); an dessen Größe an. Dann den zweiten Code z.B. in die main Methode deiner Hauptklasse und das war's. die paint() Methode rufst du nicht auf, die wird automatisch beim setVisible(true); zum Zeichen des JWindow aufgerufen. Die paint(Graphics g); Methode ist eine Methode der Klasse Component (von der JWindow über ein paar andere Klassen hinweg abgeleitet ist) und wird hier nur überschrieben.

Das sollte auch mehr ein Denkansatz sein. Keine Ahnung, wie gängige SplashScreen Implementierungen aussehen. Hab für mich noch nie einen geschrieben.

Peter
 
Transparenter Splashscreen

Hi!

Code:
import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
/*
 * Created on 20.02.2004
 * 
 * To change the template for this generated file go to Window - Preferences -
 * Java - Code Generation - Code and Comments
 */
/**
 * @author Administrator
 * 
 * To change the template for this generated type comment go to Window -
 * Preferences - Java - Code Generation - Code and Comments
 */
public class CoolSplash extends JFrame {
	private int defaultScreenWidthMargin = 50;
	private int defaultScreenHeightMargin = 37;
	private Image capture;
	private Image picture;
	private Timer timer;
	/**
	 * @param file
	 */
	public CoolSplash(File file, int w, int h, long millis) {
		int newW = w + defaultScreenWidthMargin;
		int newH = h + defaultScreenHeightMargin;
		setSize(newH, newH);
		setUndecorated(true);
		Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
		int frmX = ((int) d.getWidth() - (w + defaultScreenWidthMargin)) / 2;
		int frmY = ((int) d.getHeight() - (h + defaultScreenHeightMargin)) / 2;
		setLocation(frmX, frmY);
		try {
			Robot rob = new Robot();
			Rectangle rect = new Rectangle(frmX, frmY, newW, newH);
			capture = rob.createScreenCapture(rect);
		} catch (AWTException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		MediaTracker mt = new MediaTracker(this);
		try {
			picture = Toolkit.getDefaultToolkit().getImage(file.toURL())
					.getScaledInstance(w, h, Image.SCALE_SMOOTH);
			//ImageIO.read(file).getScaledInstance(w, h,Image.SCALE_SMOOTH);
			mt.addImage(picture, 0);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		try {
			mt.waitForAll();
		} catch (InterruptedException e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		setVisible(true);
		if (picture == null)
			picture = createImage(w, h);
		timer = new Timer();
		timer.schedule(new ExitTimerTask(this), millis);
		// TODO Auto-generated constructor stub
	}
	public static void main(String[] args) {
		new CoolSplash(new File("c:/Test.gif"), 400, 300, 5000l);
	}
	public void paint(Graphics g) {
		if (picture != null && capture != null) {
			capture.getGraphics().drawImage(picture,
					0 + defaultScreenWidthMargin / 2,
					0 + defaultScreenHeightMargin / 2, this);
			g.drawImage(capture, 0, 0, this);
		}
	}
	class ExitTimerTask extends TimerTask {
		private JFrame frm;
		public ExitTimerTask(JFrame frm) {
			this.frm = frm;
		}
		/*
		 * (non-Javadoc)
		 * 
		 * @see java.util.TimerTask#run()
		 */
		public void run() {
			// TODO Auto-generated method stub
			frm.setVisible(false);
			frm.dispose();
			System.exit(0);
		}
	}
}

Anbei test.gif

Gruß Tom
 

Anhänge

  • test.gif
    test.gif
    24 KB · Aufrufe: 2.875
Verfolge schon eine Weile diese ganze Geschichte. Frage mich nur immer warum bei den Beispielcodes ein eigener Thread erzeugt wird.
Frame/Window wird eingeblendet ausgeblendet, aber java.exe wird totzdem nicht beendet. Das Swing-Object bleibt im Hintergrund noch immer erhalten.
Da diese Operation nicht ganz so performant ist, könnte man doch einfach am Anfang des Main-Codes den Frame einblenden, Thread.sleep(), dann ausblenden.
Warum läuft nicht der Thread mit dem Frame ab, beendet sich, und parallel der Main-Code? Wenn man kein System.exit(0) gibt, hat man hinterher für jeden vergessenen Thread ein java.exe Prozess im System!?
 
Hallo!

Von welcher Implementierung sprichst du denn jetzt? Wie du schon richtig erkannt hast verwende ich einen Thread um den JFrame nach einer gewissen Anzahl von Sekunden zu auszublenden.
Wenn du kein System.exit(...) aufrufst bleibt der Java Prozess so lange erhalten bis der letzte Thread gestorben ist. Das ist jedoch nie der Fall, da in meinem Beispiel bei auslassen des System.exit(..)-Aufrufs der JFrame zwar ausgeblendet das dazugehörige Swing Thread Paket (Event Threads etc.) jedoch nicht stribt sondern einfach weiter läuft.
So ist's aber im Normalfall auch gedacht, denn die Anwendung soll ja nach dem Splashscreen auch noch weiter laufen... ;) (natürlich ohne System.exit(...) aufzurufen).

Gruß Tom
 
Moin,
wenn ich einhaken darf:
Ich hätte nun gern ähnliches, komme aber nicht auf die zündende Idee.
Wenn ich nach dem SplashScreen (JFrame/JDialog, egal) ein ganz normales JFrame in der Ansicht haben möchte, wo und wie baue ich das in den beiden obigen Beispielcodes ein? Bei diesem Code hier von Peter:
Code:
    Thread splashThread = new Thread(new SplashScreenTest());
    splashThread.start();
    while ( splashThread.isAlive() )
    {
      // do nothing
    }
    new XPInstall().show(); // mein Frame, der danach angezeigt werden soll
wird nur der Rahmen des Bildes angezeigt, nicht das Bild selbst. Lasse ich die while-Schleife weg, wird das Bild angezeigt, aber auch unverzüglich mein Frame geöffnet. Vermutlich sehe ich den Wald vor lauter Bäumen nicht.
 
Hallo!

Suchst du vielleicht sowas?

SplashScreen:
Code:
package de.tutorials;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class SplashScreen extends JFrame {
	private static final long serialVersionUID = 5654240689518773770L;

	private BufferedImage image;

	private int w, h, x, y;

	public SplashScreen(File file) {
		super("SplashScreen");
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		setUndecorated(true);
		try {
			image = ImageIO.read(file);
			w = image.getWidth();
			h = image.getHeight();

			Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
			x = (d.width - w) / 2;
			y = (d.height - h) / 2;

		} catch (IOException e) {
			e.printStackTrace();
		}
		setSize(w, h);
		setLocation(x,y);
	}

	public void display(long l) {
		setVisible(true);
		Timer timer = new Timer();
		timer.schedule(new TimerTask(){
			public void run() {
				dispose();
			}},l);
		
	}

	public void paint(Graphics g) {
		super.paint(g);
		g.drawImage(image, 0, 0, this);
	}
}

Main:
Code:
package de.tutorials;

import java.io.File;

import javax.swing.JFrame;

public class Main extends JFrame {

	private static final long serialVersionUID = 2805838986152348164L;

	public Main() {
		super("Main");
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setSize(640, 480);
	}

	public static void main(String[] args) {
		new Main().start();
	}

	private void start() {
		SplashScreen ss = new SplashScreen(new File("c:/Beispiel.jpg"));
		ss.display(5000L);
		while (ss.isDisplayable()) {
			try {
				Thread.sleep(100L);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		setVisible(true);
	}
}

HTH
Gruß Tom
 
Zurück