看了网上的资料,对于 SwingUtilities.invokeLater() 的用法还是不解。
我在 actionPerformed() 方法中新起一个线程去做事情并更新组件的状态,与使用 SwingUtilities.invokeLater() 有什么不同?我自己写了个例子,一个button 和一个progressbar,点button,progressbar开始更新,发现两种方法实现的效果是一样的,网上看到说,在新起一个线程中更新组件状态是不安全的,不安全在哪里呢?

解决方案 »

  1.   

    涉及到界面上的绘制,最好放在SwingUtilities.invokeLater() 方法中来执行,避免界面绘制错误
      

  2.   

    我就是不明白"界面绘制错误"是如何发生的?能写个例子出来:用 SwingUtilities.invokeLater() 就 work,不用就出错?
      

  3.   

    比如,有时候点了一个按钮后,你会做一件比较复杂费时的操作。
    如果你在当前线程里做,则按钮就一直是沉下状态,直到你的事情办完。按钮弹起之前,界面会失去响应。
    如果你用SwingUtilities.invokeLater()的方式,则点完之后按钮直接就弹起来了。这项费时的操作将在后台进行。这是ui设计中非常常用的方法。
      

  4.   

    你可以自己试试嘛,在按钮点击的action方法中搞个sleep,然后看看是什么情况。
    然后换成SwingUtilities.invokeLater()的方式,看有什么区别。
      

  5.   


    我有说过在 actionPerformed()中进行费时的操作吗??
      

  6.   

    我好像讲错了,我讲的那个,必须手动new 一个Thread才行。像这样:
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;public class Calendar extends JFrame implements ActionListener { private JButton button_ok = new JButton("Click me."); public Calendar() {
    super();
    this.setTitle("TEST");
    this.setLocation(500, 300);
    this.setResizable(true);
    button_ok.addActionListener(this);
    getContentPane().add(button_ok);
    pack();
    } public void actionPerformed(ActionEvent e) { new Thread(new Runnable() {
    @Override
    public void run() {
    // TODO Auto-generated method stub
    try {
    Thread.sleep(3000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getId());
    }
    }).start(); // try {
    // Thread.sleep(3000);
    // } catch (InterruptedException e1) {
    // // TODO Auto-generated catch block
    // e1.printStackTrace();
    // }
    } public static void main(String[] args) {
    System.out.println(Thread.currentThread().getId());
    Calendar CT = new Calendar();
    CT.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    CT.setVisible(true);
    }
    }
    actionPerformed方法稍加改动你就能看见效果。
    在事件分派线程中,SwingUtilities.invokeLater()还是会阻塞当前线程。
      

  7.   

    建议使用线程管理,当执行按钮中的线程时,将按钮disabled。
    线程中执行任务,执行完毕后,将按钮enabled。
      

  8.   

    都没有说到点子上去,从Sun的论坛上找到了答案和大家分享下,自己也写过例子证实了:
    ”I was calling JLabel.setText from a thread that wasn't EDT“
    Agreed it doesn't seem like a big deal because the setText() method simply saves the text in a class variable and invokes repaint(). According to the article repaint() is thread safe.However, the setText() method also creates a PropertyChangeEvent. So if you have a listener that does something with the property change event it won't be executing on the EDT, so I guess you could have a problem.后半段是重点,自己 new 一个 Thread 并简单的在里面更新组件状态是不安全的。