With the help of people on stackoverflow I was able to get the following working code of the simples GUI countdown (it just displays a window counting down seconds). My main problem with this code is the invokeLater
stuff.
As far as I understand the invokeLater
send a task to the event dispatching thread (EDT) and then the EDT execute this task whenever it "can" (whatever it means). Is it right?
To my understanding the code works like that:
In the
main
method we useinvokeLater
to show the window (showGUI
method). In other words, the code displaying the window will be executed in the EDT.In the
main
method we also start thecounter
and the counter (by construction) is executed in another thread (so it is not in the event dispatching thread). Right?The
counter
is executed in a separate thread and periodically it callsupdateGUI
. TheupdateGUI
is supposed to update GUI. And GUI is working in the EDT. So,updateGUI
should also be executed in the EDT. It is why the code for theupdateGUI
is inclosed in theinvokeLater
. Is it right?
What is not clear to me is why we call the counter
from the EDT. Anyway it is not executed in the EDT. It starts immediately a new thread and the counter
is executed there. So, why we cannot call the counter
in the main method after the invokeLater
block?
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();
}
});
}
}