Mit Hilfe der Leute auf stackoverflow konnte ich den folgenden Arbeitscode eines einfachen GUI Countdowns erhalten (der nur ein Fenster anzeigt, das Sekunden herunter zählt). Mein Hauptproblem mit diesem Code ist das invokeLater
Zeug.Wie funktioniert der Ereignisversand-Thread?
Soweit ich es verstehe invokeLater
, sendet es eine Aufgabe an den Event-Dispatching-Thread (EDT) und dann führt der EDT diese Aufgabe aus, wann immer er "kann" (was auch immer das bedeutet). Ist das richtig?
Zu meinem Verständnis, funktioniert der Code wie folgt aus:
Im
main
Methode, die wir verwendeninvokeLater
das Fenster (showGUI
-Methode) zu zeigen. Mit anderen Worten, der Code, der das Fenster anzeigt, wird in der EDT ausgeführt.Im
main
Methode Wir beginnen auch diecounter
und die Zähler (durch Konstruktion) wird in einem anderen Thread ausgeführt (es ist also nicht in dem Gewinde Ereignis Dispatching). Recht?Die
counter
wird in einem separaten Thread ausgeführt und ruft in regelmäßigen AbständenupdateGUI
auf.updateGUI
soll die GUI aktualisieren. Und die GUI arbeitet im EDT. Daher sollteupdateGUI
auch im EDT ausgeführt werden. Aus diesem Grund ist der Code für dieupdateGUI
ininvokeLater
beigefügt. Ist das richtig?
Was mir nicht klar ist, warum wir die counter
vom EDT rufen. Jedenfalls wird es im EDT nicht ausgeführt. Es startet sofort ein neuer Thread und die counter
wird dort ausgeführt. Also, Warum können wir nicht die counter
in der Hauptmethode nach dem invokeLater
Block anrufen?
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class CountdownNew {
static JLabel label;
// Method which defines the appearance of the window.
public static void showGUI() {
JFrame frame = new JFrame("Simple Countdown");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label = new JLabel("Some Text");
frame.add(label);
frame.pack();
frame.setVisible(true);
}
// Define a new thread in which the countdown is counting down.
public static Thread counter = new Thread() {
public void run() {
for (int i=10; i>0; i=i-1) {
updateGUI(i,label);
try {Thread.sleep(1000);} catch(InterruptedException e) {};
}
}
};
// A method which updates GUI (sets a new value of JLabel).
private static void updateGUI(final int i, final JLabel label) {
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
label.setText("You have " + i + " seconds.");
}
}
);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showGUI();
counter.start();
}
});
}
}
@Roman hier ist eine ausführlichere Diskussion: http://StackOverflow.com/Questions/182316/java-swing-Libraries-Thread-Safety – Kiril
@Roman * Hinweis: * Ihr Counter tut ** nicht ** starten auf der EDT beginnt es am Hauptthread. Der Zähler aktualisiert die GUI durch die updateGUI-Methode, die die Aktualisierungen auf dem EDT durchführt (wegen des Aufrufs von invokeLater). – Kiril