为什么线程无法正常睡眠?

时间:2013-03-05 13:47:50

标签: java multithreading

我正在尝试创建一个简单的JButton,在单击时会导致一个简单的JLabel将其文本更改为“second text”,之后我希望当前线程休眠几秒钟,最后JLabel更改其文本再次,这次是“第三文”。我想我已经在这里完成了它,但它并不像我想要的那样工作。下面提供的代码使JButton在指定的时间范围内冻结,就好像它被按下一样,然后标签变为第三个状态。换句话说,“秒文本”不会出现。

请告诉我应该怎么做。

谢谢。

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);
    }

}

4 个答案:

答案 0 :(得分:2)

当您考虑Java的内部结构时,文本属性的更改并不是查看结果所必须做的唯一事情。控件也必须重新绘制(可能无效)。

通过调用sleep,您实际上会阻止java GUI内部工作者重新绘制您更改的控件。它只能在睡眠结束后才会发生。

答案 1 :(得分:0)

您的GUI在线程上运行。当您将该线程休眠x秒时,您的GUI会冻结x秒。

Marko的评论中指出,“你必须使用javax.swing.Timer安排延迟事件”

答案 2 :(得分:0)

如果您在Event Dispatch Thread(处理GUI事件的线程)上休眠,则GUI将冻结。你可以从动作监听器开始一个后台线程,然后在那里睡觉。

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();
}

答案 3 :(得分:0)

在执行的操作方法中,您需要释放主GUI线程以进行更改:

因此,如果你在actionPerformed方法中打开一个新的线程,它将释放主GUI线程,然后在sleep调用label.setText(“第三个文本”)之后,这将把标签更改为第二个文本,先等待4secs然后将其更改为第三个文本

       @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();

        }