With the help of people on stackoverflow I was able to get the following working code of a simple GUI countdown (which just displays a window counting down seconds). My main problem with this code is the invokeLater stuff.
As far as I understand invokeLater, it sends a task to the event dispatching thread (EDT) and then the EDT executes this task whenever it "can" (whatever that means). Is that right?
To my understanding, the code works like this:
In the
mainmethod we useinvokeLaterto show the window (showGUImethod). In other words, the code displaying the window will be executed in the EDT.In the
mainmethod we also start thecounterand the counter (by construction) is executed in another thread (so it is not in the event dispatching thread). Right?The
counteris executed in a separate thread and periodically it callsupdateGUI.updateGUIis supposed to update the GUI. And the GUI is working in the EDT. So,updateGUIshould also be executed in the EDT. It is the reason why the code for theupdateGUIis enclosed ininvokeLater. Is that 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 can we not 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();
}
});
}
}