user1990198
user1990198

Reputation: 169

Why does the thread not sleep properly?

I am trying to make a simple JButton, which when being clicked causes a simple JLabel to change its text to "second text", after that I want the current thread to sleep for few seconds and finally the JLabel to change its text again, this time to a "third text". I think I have it done here, but it doesn't work the way I want it. The code provided below makes the JButton freeze for the specified timeframe, as if it is held down, and then the label changes to the its third state. Said in other words, the "seconds text" does not appear.

Please advise me how should it be done.

Thank you.

package testPackage;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Demo {

    public static void main(String[] args) throws InterruptedException {
        JFrame frame = new JFrame();
        JButton button = new JButton("Click me!");
        final JLabel label = new JLabel("first text");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 600);
        JPanel panel = new JPanel();
        panel.add(button);
        panel.add(label);
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                label.setText("second text");
                try {
                    Thread.currentThread();
                    Thread.sleep(4000);
                } catch (InterruptedException exc) {
                    System.out.println("Erorrrrr");
                }

            }
        });

        frame.add(panel);
        frame.setVisible(true);
    }

}

Upvotes: 1

Views: 271

Answers (4)

user_CC
user_CC

Reputation: 4776

In the action performed method you need to release the main GUI Thread for the changes to occur:

So if you open a new Thread in the actionPerformed method it will release the main GUI thread then after the sleep call the label.setText("third text") this will change the label to second text first wait for 4secs and then change it to third text

       @Override
        public void actionPerformed(ActionEvent e) {
            label.setText("second text");
            new Thread(){
              public void run(){
                try {
                  //Thread.currentThread();
                  Thread.sleep(4000);
                  label.setText("third text");
               } catch (InterruptedException exc) {
                System.out.println("Erorrrrr");
             }
           }
         }.start();

        }

Upvotes: 0

Jesse
Jesse

Reputation: 3837

If you sleep on the Event Dispatch Thread (the thread that handles GUI events), then the GUI will freeze. You could start a background thread from the action listener and to the sleeping there.

public void actionPerformed(ActionEvent e)
{
    label.setText("text 1");
    new Thread(new Runnable()
    {
        public void run()
        {
            try {
                Thread.sleep(1000);
            }catch (InterruptedException ignore){}

            // queue Swing code for execution on the EDT
            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    label.setText("text2");
                }
            });
        }
    }).start();
}

Upvotes: 0

Dariusz
Dariusz

Reputation: 22291

The change of text property is not the only thing that has to be done to see the result when you consider the internals of Java. The control also has to be redrawn (possibly invalidated).

By calling sleep you actually stop java GUI internal worker from redrawing the control you changed. It can happen only after the sleep has finished.

Upvotes: 2

Steve's a D
Steve's a D

Reputation: 3821

Your GUI runs on a thread. When you sleep that thread for x number of seconds, your GUI freezes for x number of seconds.

As noted in the comments by Marko, "you must instead schedule a delayed event with javax.swing.Timer"

Upvotes: 0

Related Questions