# splash screen mit progress bar - probleme mit invoke later



## friteuse85 (9. Aug 2008)

hallöchen,

ich wollte mir einen splashscreen mit einem fortschrittbalken basteln. hier mal das code gerüst: 
	
	
	
	





```
package splashscreen;

import java.awt.BorderLayout;
import java.awt.FlowLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JWindow;

public class SplashScreenTest {
	
	static int count = 0;
	static SplashScreen screen;
	static boolean useInvokeLater = false;

	public static void main(String[] args) {
		if(!useInvokeLater){
		createSplash();
		showMainGUI();
		}
		else{
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				createSplash();
			}
		});
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				showMainGUI();
			}
		});
		}
	}
	
	public static void createSplash(){
		screen = new SplashScreen();
		screen.showSplash();
		screen.pack();
		screen.setVisible(true);
		System.out.println("Splash created");
	}

	public static void showMainGUI() {
		// nun das eigentliche gui aufbauen und dabei die progressBar updaten
		int i = 0;
		JFrame frame = new JFrame();
		JPanel panel = new JPanel(new FlowLayout());
		frame.getContentPane().add(panel);
		while(i<10){
		panel.add(new JLabel("Shit happpppenz!"));
		screen.progressBar.setValue(i* 10);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			i++;	
		}
		frame.pack();
		frame.setVisible(true);
		
	}
}

class SplashScreen extends JWindow {
	public JProgressBar progressBar;

	public void showSplash() {
		setLocationRelativeTo(null);
		JPanel content = (JPanel) getContentPane();
		progressBar = new JProgressBar(0, 100);
		add(progressBar, BorderLayout.CENTER);
	}
}
```

so wies da steht funktionierts wie's soll, aber das problem ist, das ich es nicht über invoke later starten kann (wie man ja eigentlich sollte). entweder wird dann die progressbar erst am ende auf 100% upgedated, sie erscheint gar nicht ...

hat jemand einen tipp wie man das verbessern könnte (wie gesagt funktionieren tuts aber eben...)

thxxxxxxxxxxxxxx


----------



## Guest (9. Aug 2008)

ach ja. ich hab auch schon probiert die progressbar über invokelater upzudaten. funzt auch nicht (respektive wird erst ganz am schluss auch 100% upgedatet).


----------



## gasthier (10. Aug 2008)

ich würde mich eher fragen, warum mein Programm einen splashscreen benötigt, schlechter code? für 3 sekunden braucht man keinen splash, da der user in 3 sekunden nicht in der Lage ist diesen zu lesen/schauen ab der 1. sekunde an wo der splash plötzlich auftaucht.


----------



## SebiB90 (10. Aug 2008)

ist klar das die Progressbar nicht aktualisiert wird.
repaint findet im EDT statt. Durch invokeLater führst du deinen code im EDT aus. Also ist die Schleife wo hochgezählt wird im EDT und blockiert den. Repaint ist erst möglich wenn dein code abgearbeitet ist.


----------



## Guest (10. Aug 2008)

gasthier hat gesagt.:
			
		

> ich würde mich eher fragen, warum mein Programm einen splashscreen benötigt, schlechter code? für 3 sekunden braucht man keinen splash, da der user in 3 sekunden nicht in der Lage ist diesen zu lesen/schauen ab der 1. sekunde an wo der splash plötzlich auftaucht.



löst du deine probleme immer so :applaus: 




			
				SebiB90 hat gesagt.:
			
		

> ist klar das die Progressbar nicht aktualisiert wird.
> repaint findet im EDT statt. Durch invokeLater führst du deinen code im EDT aus. Also ist die Schleife wo hochgezählt wird im EDT und blockiert den. Repaint ist erst möglich wenn dein code abgearbeitet ist.



danke für den hinweis  :toll: 
repaint wird also erst aufgerufen wenn die event-queue leer ist?


----------



## gasthier (10. Aug 2008)

> löst du deine probleme immer so :applaus:



hinsichtlich eines Splash der unnötig ist wie ein Kropf ja... früher luden die programme länger wie heute, dennoch gabs kein splash mit Namen der Firma was sich toll liest...


----------



## Marco13 (11. Aug 2008)

_repaint wird also erst aufgerufen wenn die event-queue leer ist?_

Um mal ... spitzfindig.... oder präzise zu sein: "repaint()" kann man aufrufen, wann man will. Das eigentliche Neuzeichnen (paint(Graphics g)) passiert "wenn die Queue leer ist" (bzw. wenn das Neuzeichnen eben an dere Reihe ist).

@gasthier: _früher luden die programme länger wie heute, dennoch gabs kein splash mit Namen der Firma was sich toll liest..._
Tsts... Früher gab es doch noch gar keine Computer! :meld:


----------



## kleiner_held (11. Aug 2008)

1. Das createSplash() sollte gar nicht mit invokeLater aufgerufen werden.
2. beim showMainGUI() muesste theoretisch nur der Teil

```
screen.progressBar.setValue(i* 10);
```
   in ein invoke later gekaspselt werden, auf keinen Fall aber das 

```
Thread.sleep(1000);
```
   In der Praxis ist das aber mMn invokeLater() in dem Fall auch unnoetig, da JProgressBar und BasicProgressBarUI bzgl. setValue() thread save sein sollten.

PS: Es gibt auch eine eingebaute Splash-Screen Funktionalitaet von Java, dabei ist allerdings ein ProgressBar ein wenig komplizierter umzusetzen:
Splash-Screen Functionality in Java SE 6


----------

