# Wieso Fenster im EDT sichtbar machen?



## SebiB90 (13. Jul 2008)

Hallo,

hab vllt eine dumme Frage. Nur ich verstehs halt nicht.
Im Forum sehe ich oft so ein Code in der main methode:

```
EventQueue.invokeLater(new Runnable() { 
            @Override 
            public void run() { 
                new JFrame().setVisible(true); //JFrame = das Hauptfenster der Anwendung
            } 
        });
```

wieso wird die Anweisung in die EventQueue gepackt? Wieso nicht einfach nur?


```
new JFrame().setVisible(true);
```

Ich weiß, dass mit der ersten Variante das setVisible() in dem EDT ausgeführt wird.
Aber was bringt das für ein Vorteil?

Mfg
SebiB90


----------



## André Uhres (13. Jul 2008)

SebiB90 hat gesagt.:
			
		

> Aber was bringt das für ein Vorteil?


Der Code wird dadurch "thread safe".
Der meiste Code, der Swing Methoden aufruft, muss auf dem "event dispatch thread" laufen.
Das ist notwendig, weil die meisten Swing Methoden nicht "thread safe" sind.
mehr


----------



## Illuvatar (13. Jul 2008)

Eine Frage dazu: Ich sehe es nur selten, aber manche verlagern auch ein setVisible aus der main-Methode in den EDT. Bringt das irgendwas? Der EDT läuft ja noch nichtmal bevor das erste Fenster sichtbar ist, oder? Wäre das nur für den Fall, dass die main-methode innerhalb einer VM öfters aufgerufen wird, sinnvoll?


----------



## SebiB90 (13. Jul 2008)

Illuvatar hat gesagt.:
			
		

> Eine Frage dazu: Ich sehe es nur selten, aber manche verlagern auch ein setVisible aus der main-Methode in den EDT. Bringt das irgendwas? Der EDT läuft ja noch nichtmal bevor das erste Fenster sichtbar ist, oder? Wäre das nur für den Fall, dass die main-methode innerhalb einer VM öfters aufgerufen wird, sinnvoll?


genau das war doch meine frage


----------



## André Uhres (13. Jul 2008)

Folgenden Code kann ich keine 40 mal starten, ohne daß er wenigstens einmal 
einfach hängen bleibt (also der JFrame wird nicht sichtbar).
Wenn man das Ding mit "invokeLater" startet, ist das  Problem behoben.

```
package demo;

/**
 * Main window
 * @author      Andreas Dvorak
 */
import java.awt.*;
import javax.swing.*;

public class MainFrame {

    public boolean status = true;
    private JFrame frame = null;

    public MainFrame() {
        initFrame();
    }

    public void initFrame() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 620);
        frame.setTitle("Bestenliste");
        // In der Mitte des Bildschirms platzieren
        frame.setLocation(
                (Toolkit.getDefaultToolkit().getScreenSize().width -
                frame.getSize().width) / 2,
                (Toolkit.getDefaultToolkit().getScreenSize().height -
                frame.getSize().height) / 2);
        StartPanel panel = new StartPanel();
        frame.setContentPane(panel.getPanel());
        frame.setVisible(true);
    }

    public static void main(final String[] args) {
        //DU MUSST DAS DING MIT "invokeLater" STARTEN !!!
//        java.awt.EventQueue.invokeLater(new Runnable() {
//
//            public void run() {
                new MainFrame();
//            }
//        });
    }
}

class StartPanel {

    private String version = "1.0";

    public JPanel getPanel() {
        JPanel panel = new JPanel();
        JPanel uppanel = new JPanel();
        uppanel.setBackground(new java.awt.Color(238, 238, 238));
        JPanel midpanel = new JPanel();
        midpanel.setBackground(new java.awt.Color(238, 238, 238));
        JPanel downpanel = new JPanel();
        downpanel.setBackground(new java.awt.Color(238, 238, 238));
        JPanel statuspanel = new JPanel();
        statuspanel.setBackground(new java.awt.Color(238, 238, 238));
        JTextPane text1 = new JTextPane();
        text1.setBackground(new java.awt.Color(238, 238, 238));
        JTextPane text2 = new JTextPane();
        text2.setBackground(new java.awt.Color(238, 238, 238));
        JTextPane text3 = new JTextPane();
        text3.setBackground(new java.awt.Color(238, 238, 238));
        JTextPane statustext = new JTextPane();
        statustext.setBackground(new java.awt.Color(238, 238, 238));
        GridLayout gridLayout = new GridLayout();
        gridLayout.setRows(4);
        gridLayout.setColumns(1);
        panel.setLayout(gridLayout);
        FlowLayout flowLayout = new FlowLayout();
        flowLayout.setHgap(20);
        flowLayout.setVgap(40);
        uppanel.setLayout(flowLayout);
        panel.add(uppanel);
        panel.add(midpanel);
        panel.add(downpanel);
        panel.add(statuspanel);
        text1.setText("Bestenliste für die Verwaltung von Laufergebnissen");
        text1.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 18));
        text1.setEditable(false);
        text2.setText("Andreas Dvorak");
        text2.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 18));
        text2.setEditable(false);
        text3.setText("Version " + version);
        text3.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 18));
        text3.setEditable(false);
        statustext.setText("Status: registriert");
        statustext.setFont(new java.awt.Font("Arial", java.awt.Font.BOLD, 14));
        statustext.setEditable(false);
        uppanel.add(text1);
        midpanel.add(text2);
        downpanel.add(text3);
        statuspanel.add(statustext);
        return panel;
    }
}
```


----------



## Illuvatar (14. Jul 2008)

SebiB90 hat gesagt.:
			
		

> genau das war doch meine frage


Ups, überlesen dass du auch die main-Methode meintest.

@Andre: Na gut, ich werds mir merken. Ich finds nur seltsam, ich hab das noch nie so gemacht, und es ist mir noch nie aufgefallen dass es nicht funktioniert hätte. Auch im Javabuch stand das glaub ich immer ohne invokeLater.


----------



## Verjigorm (14. Jul 2008)

Also wenn ich ne Gui starte, hab ich auch noch niemals invokeLater benutzt und noch niemals Probleme mit gehabt.

Ich frag mich auch immer nach dem Sinn.


----------



## AlArenal (14. Jul 2008)

Hier ist wieder mein alter Lieblingslink: http://www.javalobby.org/eps/galbraith-swing-2/


----------



## André Uhres (15. Jul 2008)

Illuvatar hat gesagt.:
			
		

> ich hab das noch nie so gemacht, und es ist mir noch nie aufgefallen dass es nicht funktioniert hätte.


_Some Swing component methods are labelled "thread safe" in the API specification; 
these can be safely invoked from any thread. All other Swing component methods *must be invoked 
from the event dispatch thread*. *Programs that ignore this rule may function correctly most of the time, 
but are subject to unpredictable errors that are difficult to reproduce.*_
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/dispatch.html
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/initial.html



			
				Verjigorm hat gesagt.:
			
		

> Also wenn ich ne Gui starte, hab ich auch noch niemals invokeLater benutzt und noch niemals Probleme mit gehabt.
> Ich frag mich auch immer nach dem Sinn.


Liest eigentlich auch irgendjemand das, was in diesem Thread geschrieben wurde  :roll:  :?:
Wer danach immer noch nach dem Sinn fragt, der ist aber ein Komischer, oder er will es einfach nicht verstehen :shock:


----------



## SebiB90 (15. Jul 2008)

Wie siehts eigentlich bei AWT aus?
Ist es dort das gleiche oder ist das nur bei swing so?


----------



## The_S (16. Jul 2008)

@André heißt das, dass wirkliche ALLE Methoden in Swing-Componenten, die nicht als thread-safe markiert sind, über den EDT aufgerufen werden müssen? Also auch welche, die die Darstellung eigentlich gar nicht betreffen!?


----------



## L-ectron-X (16. Jul 2008)

SebiB90 hat gesagt.:
			
		

> Wie siehts eigentlich bei AWT aus?
> Ist es dort das gleiche oder ist das nur bei swing so?


Das betrifft nur Swing.


----------



## André Uhres (16. Jul 2008)

Hobbit_Im_Blutrausch hat gesagt.:
			
		

> @André heißt das, dass wirkliche ALLE Methoden in Swing-Componenten, die nicht als thread-safe markiert sind, über den EDT aufgerufen werden müssen? Also auch welche, die die Darstellung eigentlich gar nicht betreffen!?


Afaik wird die Richtlinie nirgendwo eingegrenzt. Ausserdem haben ja wohl alle Swing Komponentenmethoden
irgendeinen Bezug zur Oberfläche, was die strikte Einhaltung der Richtlinie sinnvoll erscheinen lässt.


----------



## byte (16. Jul 2008)

Das Thema ist in SWT eindeutig besser umgesetzt. Da fliegt nämlich eine Exception, wenn man aus einem anderen Thread GUI-Komponenten manipuliert. Auf diese Weise kann man nichts falsch machen.


----------



## The_S (16. Jul 2008)

Ich meine z. B. Methoden wie JFileChooser#getSelectedFile ... die Methode wird wohl meist dann aufgerufen, wenn der JFileChooser gar nicht mehr sichtbar ist und sollte somit wohl keine Auswirkungen auf die Oberfläche haben!?


----------



## André Uhres (16. Jul 2008)

Hobbit_Im_Blutrausch hat gesagt.:
			
		

> Ich meine z. B. Methoden wie JFileChooser#getSelectedFile ... die Methode wird wohl meist dann aufgerufen, wenn der JFileChooser gar nicht mehr sichtbar ist und sollte somit wohl keine Auswirkungen auf die Oberfläche haben!?


Aber die Selektion kommt doch durch ein Event auf der Oberfläche. 
Demnach muss man auch in diesem Fall mit dem EDT synchronisieren.


----------



## byte (16. Jul 2008)

Grundsätzlich sollten wohl alle Getter problemlos funktionieren, weil sie i.d.R. nur einen Wert zurückliefern und die GUI nicht manipulieren. Anders ist es bei Settern. 
Wenn ich z.B. bei einem JLabel den Text setze, dann wird der Repaint-Mechanismus angestoßen und die GUI aktualisiert. Wenn ich mir hingegen den Text des JLabels mit getText() hole, dann hat das keine Auswirkungen auf die GUI, muss also nicht asynchron passieren.

Aber die Doku ist da sehr schwammig. Ich meine mich z.B. zu erinnern, dass JLabel#setText() thread-safe ist. In der Javadoc ist davon jedoch nichts zu lesen.

Sun hätte einfach eine RuntimeExc. werfen sollen und fertig. Das würde es dem Programmierer sehr vereinfachen und würde wahrscheinlich die Qualität vieler Swing-Clients deutlich verbessern.


----------



## byte (16. Jul 2008)

André Uhres hat gesagt.:
			
		

> Aber die Selektion kommt doch durch ein Event auf der Oberfläche.
> Demnach muss man auch in diesem Fall mit dem EDT synchronisieren.


Ne:

JFileChooser:

```
public File getSelectedFile() {
	return selectedFile;
    }
```


----------



## André Uhres (16. Jul 2008)

Der Getter muss trotzdem synchronisiert werden, wenn man einen sinnvollen Wert haben möchte. Der Sinn ist ja, den vom Benutzer ausgewählten Wert zu bekommen.


----------



## byte (16. Jul 2008)

Bekommst Du doch. Der Getter triggert kein Event und hat somit keine Nebeneffekte auf den EDT.


----------



## André Uhres (16. Jul 2008)

Darum geht's ja auch nicht :wink:
Ich bekomm den Wert nur wenn ich synchronisiere. Anders ist es ja gar nicht denkbar.


----------



## byte (16. Jul 2008)

Verstehe ich nicht.


----------



## André Uhres (16. Jul 2008)

Wenn der Benutzer noch nix ausgewählt hat, muss das Programm darauf warten, daß er es tut, um die Selektion auslesen und verarbeiten zu können.


----------



## byte (17. Jul 2008)

Was hat das jetzt mit invokeLater zu tun? 
Die Methode liefert das selektierte File, egal ob schon was selektiert wurde oder nicht. Natürlich ist es sinnfrei, nebenläufig darauf zuzugreifen, wenn man die endgültige Selektion haben will.


----------



## Hollow (17. Jul 2008)

Ähm das mit dem invokeLater und Componenten, trifft das auch auf den Fall zu das ich die PaintComponent von nem
JPanel überschreibe? Wie zum Beispiel bei dem Spiel in Quaxlis Tutorial. Muss ich das repaint dann auch in ein
invokeLater packen?


----------



## André Uhres (17. Jul 2008)

byto hat gesagt.:
			
		

> Was hat das jetzt mit invokeLater zu tun?


Ich weiss nicht, was du jetzt wieder mit invokeLater willst  :roll: . 
Wir sprechen ja jetzt einfach nur darüber, daß alle Swing Komponentenmethoden,
die nicht als "thread safe" gekennzeichnet sind, vom "event dispatch thread" aus aufgerufen werden müssen.



			
				byto hat gesagt.:
			
		

> Die Methode liefert das selektierte File, egal ob schon was selektiert wurde oder nicht. Natürlich ist es sinnfrei, nebenläufig darauf zuzugreifen, wenn man die endgültige Selektion haben will.


Das versuch ich ja die ganze Zeit klar zu machen.



			
				Hollow hat gesagt.:
			
		

> Muss ich das repaint dann auch in ein invokeLater packen?


Nein, die Methode repaint() ist "thread safe".


----------



## byte (17. Jul 2008)

André Uhres hat gesagt.:
			
		

> byto hat gesagt.:
> 
> 
> 
> ...



Ja, genau darüber sprechen wir. Und genau darauf bezieht sich das von mir angesprochene invokeLater...

Im übrigen werden in meiner Javadoc nicht alle thread-safe Methoden in der Javadoc als solche gekennzeichnet.  Du schreibst z.B. dass repaint() thread-safe ist. Wo findest Du das in der Javadoc? In der Beschreibung zu _Component#repaint()_ finde ich nichts dergleichen. Genauso wenig wie in anderen Methodenbeschreibungen, die bekannterweise thread-safe sind (wie afaik _JLabel#setText()_).

Aus diesem Grund würde ich im Zweifel auf Nummer-Sicher gehen und Aufrufe aus einem anderen Thread, die die GUI beeinflussen, per invokeLater machen. Einfache Getter hingegen (wie bei JFileChooser#getSelectedFile()) können direkt aufgerufen werden. Im Zweifel hilft immer ein Blick in die Sourcen, ob diejenige Methode ein EDT-Event triggert oder einfach nur einen Wert zurückliefert.

Der Grund, warum man bestimmte Methoden aus einem zweiten Thread nicht direkt aufrufen soll, ist ja eben, wenn diese EDT-Events feuern. Der EDT könnte in diesem Moment beschäftigt sein, was zur Folge hätte, dass die GUI träge reagiert, hängt oder sich gar fehl verhält. Wenn die Methoden hingegen keine EDT-Events feuern, gelten die gleichen Grundsätze wie bei der ganz normalen nebenläufigen Programmierung. Swing ist schließlich kein Hexenwerk.


----------



## SlaterB (17. Jul 2008)

> Im Zweifel hilft immer ein Blick in die Sourcen, ob diejenige Methode ein EDT-Event triggert oder einfach nur einen Wert zurückliefert.

also zum Zurückgeben reicht ein Blick auf den Rückgabewert + Namen der Operation (get)
oder gibts gar Beispiele für get-Operationen, die sowas böses machen?


----------



## byte (17. Jul 2008)

Wenn sich Sun an seine eigenen Konventionen hält - also dass Getter wirklich nur einen Wert zurückliefern - dann sollten Getter perse problemlos sein. Skeptisch wäre ich immer bei _firePropertyChange(...)_ bzw. generell bei Settern oder Methoden, die direkt oder indirekt die GUI verändern.


----------



## Marco13 (17. Jul 2008)

Hab jetzt nicht alles nachvollzogen, aber streue mal so ein, dass der Aufruf einer get-Methode _außerhalb_ des EDT durchaus ein unerwünschtes Ergebnis liefern kann, wenn die set-Methoden im EDT aufgerufen werden...

```
SwingUtilities.invokeLater() { ... textField.setText("Hallo"); ... }
String nichtHallo = textField.getText(); // Passiert das VOR oder NACH dem "setText"?
```
aber das sollte klar sein....


----------



## byte (17. Jul 2008)

Dass man bei invokeLater die Synchronität verliert sollte klar sein, jo. Es gibt übrigens auch noch invokeAndWait().

Fakt ist aber, dass das Konzept nicht gut durchdacht ist. Laut André Uhres ist es ja irgendwo dokumentiert, welche Methoden thread-safe sind - jedoch offenbar nicht dort, wo man es vermutet (in der Javadoc). Bei SWT fliegt eine Laufzeit-Exception, das ist wesentlich sicherer. Der Entwickler wird gezwungen, es richtig zu machen.


----------



## André Uhres (17. Jul 2008)

byto hat gesagt.:
			
		

> Ja, genau darüber sprechen wir. Und genau darauf bezieht sich das von mir angesprochene invokeLater...


invokeLater macht gewöhnlich keinen Sinn, wenn man auf dem EDT ist, wovon man bei  einem EventListener ausgehen kann:
wenn der Benutzer eine Selektion macht, schickt er einen Event auf den EDT.



			
				byto hat gesagt.:
			
		

> Du schreibst z.B. dass repaint() thread-safe ist. Wo findest Du das in der Javadoc? In der Beschreibung zu _Component#repaint()_ finde ich nichts dergleichen.


Die Swing Malmechanismen werden hier erklärt: http://wiki.byte-welt.net/wiki/Malen_in_AWT_und_Swing
Ein entsprechender Link ist in der API enthalten.



			
				byto hat gesagt.:
			
		

> Genauso wenig wie in anderen Methodenbeschreibungen, die bekannterweise thread-safe sind (wie afaik _JLabel#setText()_).


JTextComponent#setText ist "thread safe", JLabel#setText aber nicht.
Alle Swing Komponentenmetoden, die nicht "thread safe" sind, müssen vom EDT aus aufgerufen werden.
Getter aus anderen Threads aufzurufen macht keinen Sinn, wie du schon richtig erkannt hast:


			
				byto hat gesagt.:
			
		

> Natürlich ist es sinnfrei, nebenläufig darauf zuzugreifen, wenn man die endgültige Selektion haben will.


----------



## Verjigorm (17. Jul 2008)

Könnte dazu nicht mal jemand ein paar Zeilen Beispielcode tippseln?
So in der Art "So ist es falsch" und "So macht man es richtig"
Vielelicht direkt in die FAQ damit ...

So ganz blick ich da nämlich nich durch


----------



## André Uhres (17. Jul 2008)

Verjigorm hat gesagt.:
			
		

> Könnte dazu nicht mal jemand ein paar Zeilen Beispielcode tippseln?


http://www.java-forum.org/de/viewtopic.php?p=430319#430319


----------



## byte (17. Jul 2008)

byto hat gesagt.:
			
		

> Natürlich ist es sinnfrei, nebenläufig darauf zuzugreifen, wenn man die endgültige Selektion haben will.


Jetzt verstanden? :roll:


----------



## André Uhres (17. Jul 2008)

byto hat gesagt.:
			
		

> So habe ich das nicht geschrieben!


 :lol: Steht zumindest so unter deinem Namen, aber vielleicht hat's ja deine Mutti diktiert :lol: 



			
				byto hat gesagt.:
			
		

> Möglich ist es allemal, auch wenn Du das nicht einsehen willst. :roll:


Daß es möglich ist, seh ich ein. Nur richtig ist es nicht, sondern sinnfrei, 
wie du's geschrieben hast, auch wenn du das jetzt wieder abstreitest  :lol:


----------



## byte (17. Jul 2008)

kA warum meine Antwort auf Dein letztes Post jetzt vor deinem steht lol


----------



## Verjigorm (17. Jul 2008)

André Uhres hat gesagt.:
			
		

> Verjigorm hat gesagt.:
> 
> 
> 
> ...



schön ... du schreibst, du kannst das Ding nicht 40mal starten ohne irgendeinen "Fehler" ...
Hab irgendwelche JFrames schon tausendfach ohne invokelater gestartet und nie ein Problem gehabt, ist das nun Glück? oO

Und was hier geredet wird mit Methodenaufrufe die nicht thread-safe sind ..
muss ich dann um jeden 2. Methodenaufruf invokelater() machen oder wie?

(Ich versuchs ja zu verstehen , aber der positive/negative Effekt von machen bzw. nicht machen ist mir überhaupt nicht erkennbar)


----------



## André Uhres (17. Jul 2008)

byto hat gesagt.:
			
		

> byto hat gesagt.:
> 
> 
> 
> ...


Das hab ich genauso zitiert und auch so verstanden (ein Wort grösser darzustellen ändert kaum etwas am Informationsgehalt).
Eine Richtlinie durch eine Theorie in Frage zu stellen, ist kaum förderlich, 
es sei denn, die  Theorie bringt auch einen wesentlichen praktischen Nutzen.
Falls es dich jedoch beruhigt, wiederhole ich: ich seh ein, daß es möglich ist (mehr nicht).



			
				Verjigorm hat gesagt.:
			
		

> Hab irgendwelche JFrames schon tausendfach ohne invokelater gestartet und nie ein Problem gehabt, ist das nun Glück?


Ja. 
_Some Swing component methods are labelled "thread safe" in the API specification; 
these can be safely invoked from any thread. All other Swing component methods *must be invoked 
from the event dispatch thread*. *
Programs that ignore this rule may function correctly most of the time, 
but are subject to unpredictable errors that are difficult to reproduce.*_
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/dispatch.html
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/initial.html



			
				Verjigorm hat gesagt.:
			
		

> Und was hier geredet wird mit Methodenaufrufe die nicht thread-safe sind ..
> muss ich dann um jeden 2. Methodenaufruf invokelater() machen oder wie?


Wenn du die GUI wie empfohlen startest, bist du auf dem EDT und bleibst auch drauf. 
Du brauchst dann kein zusätzliches invokelater. Der Aufruf von invokelater ist aber notwendig, 
wenn du einen speziellen Workerthread (auch Backgroundthread genannt) startest 
und von dort aus Swingkomponenten ansprichst. Workerthreads werden benötigt, 
damit der EDT nicht durch langwierige Prozesse blockiert wird.


----------



## byte (17. Jul 2008)

Du hast recht und ich meine Ruhe...


----------



## Verjigorm (17. Jul 2008)

André Uhres hat gesagt.:
			
		

> Wenn du die GUI wie empfohlen startest, bist du auf dem EDT und bleibst auch drauf.
> Du brauchst dann kein zusätzliches invokelater. Der Aufruf von invokelater ist aber notwendig,
> wenn du einen speziellen Workerthread (auch Backgroundthread genannt) startest
> und von dort aus Swingkomponenten ansprichst. Workerthreads werden benötigt,
> damit der EDT nicht durch langwierige Prozesse blockiert wird.



Ok gut, ich denke soweit hab ich es wohl gerafft.
Nur deine Aussage mit dem Workerthread irritiert mich nun etwas 

Starte GUI mit Invokelater -> EDT

Wenn ich nun nen WorkerThread starte, arbeitet der aber NICHT auf dem EDT (was ja der Sinn der Sache ist), wird aber vom EDT aus gestartet, weil wir die GUI ja daraus starten.
Oder seh ich das falsch?  :?:
Danke für die Geduld


----------



## André Uhres (17. Jul 2008)

richtig


----------



## Verjigorm (17. Jul 2008)

Gut gut, mein Mosaik ist langsam fertig 

Wenn ich also nun meine GUI über invokeLater gestartet habe und z.B. per Buttonclick nen JDialog aufmache, muss ich aber nicht nochmal invokeLater benutzen?

Bzw. generell: Wann benutzt man denn sonst noch invokeLater und invokeAndWait?


----------



## André Uhres (18. Jul 2008)

Verjigorm hat gesagt.:
			
		

> Wenn ich also nun meine GUI über invokeLater gestartet habe und z.B. per Buttonclick nen JDialog aufmache, muss ich aber nicht nochmal invokeLater benutzen?


nein



			
				Verjigorm hat gesagt.:
			
		

> Bzw. generell: Wann benutzt man denn sonst noch invokeLater und invokeAndWait?


invokeLater benutzt man um den Code später auf dem EDT auszuführen 
(z.B. um ein JLabel von einem Workerthread aus zu aktualisieren).
invokeAndWait benutzt man um das Programm zu blockieren, bis der Code auf dem EDT ausgeführt wurde
(z.B. um ein JLabel von einem Workerthread aus zu aktualisieren und erst weiterzumachen, wenn das geschehen ist).

Java 6 hat auch noch SwingWorker eingeführt, um zeitaufwendige oberflächenbezogene Prozesse in einem speziellen Thread auszuführen.


----------

