3

I have a JFrame on which I want to simulate a countdown (like a rocket launch). So I set up the frame by hiding various controls (setVisible(false)) and displaying a JLabel with the text (this is the text that is supposed to countdown: 3, 2, 1, Go).

The text on that JLabel starts out at "3". My intent is to simply have the execution of the program wait for 1 second, then change the text to "2", wait another second, change to "1", etc.). At the end, I hide the JLabel and redisplay all of the controls and everything proceeds as normal.

What I am doing isn't working. It seems to wait for the correct amount of time, and when it is done, my JFrame looks great and works as intended. But during the 4 seconds of the countdown method, all I see is a white JFrame. Not the 3, 2, 1 that I want.

Here is my code. Can anyone see what I am doing wrong? Thanks!

public void countdown() {
    long t0, t1;        

    myTest.hideTestButtons(true);
    myTest.repaint();

    t0 =  System.currentTimeMillis();
    do {
        t1 = System.currentTimeMillis();
    } while ( (t1 - t0) < 1000);

    myTest.TwoSeconds();
    myTest.repaint();
    t0 =  System.currentTimeMillis();
    do {
        t1 = System.currentTimeMillis();
    } while ( (t1 - t0) < 1000);


    myTest.OneSecond();
    myTest.repaint();
    t0 =  System.currentTimeMillis();
    do {
        t1 = System.currentTimeMillis();
    } while ( (t1 - t0) < 1000);


    myTest.Go();
    myTest.repaint();
    t0 =  System.currentTimeMillis();
    do {
        t1 = System.currentTimeMillis();
    } while ( (t1 - t0) < 1000);

    myTest.hideTestButtons(false);
    myTest.repaint();
}

public void TwoSeconds() {
    lblCountdown.setText("2");
}

public void OneSecond() {
    lblCountdown.setText("1");
}

public void Go() {
    lblCountdown.setText("Go!");
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
AndroidDev
  • 20,466
  • 42
  • 148
  • 239

2 Answers2

3

You'll want to use javax.swing.Timer to do the timing on your application.

What's happening is that you're running everything on one thread - so the UI (which runs on a separate thread) doesn't have an opportunity to update.

If you want an example of how this works, you can look at this answer: https://stackoverflow.com/a/1006640/1515592

Community
  • 1
  • 1
Nick Rippe
  • 6,465
  • 14
  • 30
2

Use a Timer instead. An active wait is in most of the cases highly discouraged. Here is the type of code you'll need to integrate:

final Timer ti = new Timer(0, null);
ti.addActionListener(new ActionListener() {
    int countSeconds = 3;

    @Override
    public void actionPerformed(ActionEvent e) {
        if(countSeconds == 0) {
            lblCountdown.setText("Go");
            ti.stop();
        } else {
            lblCountdown.setText(""+countSeconds);
            countSeconds--;
        }
    }
});
ti.setDelay(1000);
ti.start();
aymeric
  • 3,877
  • 2
  • 28
  • 42
  • Thank you. I have some better code, but still can't get this to work. I marked your answer as the solution. Since my code is now totally different, I'll re-post rather than pollute this thread. Thanks again! – AndroidDev Aug 18 '12 at 22:31