Using the sleep method()


Good afternoon, everyone. Need a tip: the program should change the label on the button sequentially from "10" to "0". To make sure that each label change occurs at a small interval I used the sleep method().

As a result, after pressing the button, the prog freezes and then immediately outputs "0". What could be the problem? A piece of code is presented below.

try {
    for (int i = 10; i > -1; i--) {
        Thread.sleep(500);
        String iString = String.valueOf(i);
        button.setText(iString);
    }
} catch (InterruptedException qq) {
    qq.printStackTrace();
}
Author: sercxjo, 2014-07-26

2 answers

Welcome to the fascinating world of UI programming! You'll have to retrain a bit: it's not like in command-line programs. Here, all background tasks related to the interface do not occur immediately, as soon as you command, but are mixed with your work. All this happens in a fixed thread, the so-called UI thread.

What happens in your code?

  1. You block the UI flow for half a second, then set the button text. An internal flag is set in the graphics library, which says "when there is a free minute, you need to update the button".
  2. You immediately block the UI flow again for half a second, and reset the button text. Since "free minute" (aka " idle loop") it never came, the text did not have time to update. In addition, there is no one to handle mouse and keyboard events during the lock (because the UI thread is busy with sleep ' s), so the program looks hung up.
  3. Then you set the button text again, this does not change anything, since the flag indicating the need for an update is already cocked.
  4. And so on, 11 times.
  5. Eventually, when your loop is over, the UI thread is finally free, and can render your changes. You finally see 0.

What is the problem? You should not perform long operations in the UI thread. Thread.sleep is one of these operations, but many also read files, load data from the network, or access the database. You have the right to load the UI stream with work for only a few milliseconds. For the entire duration of a long operation running in the UI thread, the application will look hung, and the UI event handlers will not be called. This behavior of the program immediately turns it into a student craft.

Updating the UI, reacting to the mouse, redrawing controls-everything happens in the UI thread, at a time when this thread is not busy with anything. A good program with a UI should be event-oriented, not imperative: you do not have to steer the course of the program yourself, but only respond to events with short-term handlers.

What should I do? There are two ways. A simple way that is quite suitable for your purposes: do not block the UI thread, but use the timer that comes with your UI library. It will call your handler at the right time, you will set the button text there, and finish processing. by doing this, you will release the UI thread so that it can update UI.

A complex path that applies if you really need to perform a lengthy operation. In this case, you create a separate thread (thread), in which you perform the desired operation. You send the results of the work to the UI thread at the right time, which should simply update the UI. Note that in this case, programming becomes much more complicated, since you will have to take care of synchronization, locking, and communication between threads (just the global variable does not roll). But for your case, this is unnecessary, a simple timer will be enough.

 12
Author: VladD, 2014-07-26 13:35:03

What if?

Thread th = new Thread(new Runnable() {
    for (int i = 10; i > -1; i--) {
        String iString = String.valueOf(i);
        button.setText(iString);
        sleep(1000);
    }
});
th.start();
 0
Author: bvn13, 2014-08-01 08:25:32