Swing 是否调用Elater()

Swing 是否调用Elater(),swing,invokelater,Swing,Invokelater,我正在编写一个示例来展示SwingUtilities.invokeLater()的用法。我开始意识到我编写的这个简单示例(包括代码)并不保证invokeLater()的使用。我确实遇到过需要使用invokeLater()的情况,但我忘记了在何时何地使用。我也明白,在非EDP线程中,我应该使用invokeLater(),但在我的情况下,我似乎不需要它,它工作得很好。我希望有人能告诉我为什么在这段代码中不需要使用invokeLater()。我希望我的showcase代码中没有bug 顺便说一句,我在

我正在编写一个示例来展示SwingUtilities.invokeLater()的用法。我开始意识到我编写的这个简单示例(包括代码)并不保证invokeLater()的使用。我确实遇到过需要使用invokeLater()的情况,但我忘记了在何时何地使用。我也明白,在非EDP线程中,我应该使用invokeLater(),但在我的情况下,我似乎不需要它,它工作得很好。我希望有人能告诉我为什么在这段代码中不需要使用invokeLater()。我希望我的showcase代码中没有bug

顺便说一句,我在Linux和Windows中使用JDK1.6/1.7

谢谢

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class HelloButton {
    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setLayout(new FlowLayout());
        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        JSplitPane pane = new JSplitPane();
        f.add(pane);
        final JLabel clickMessage = new JLabel("No Message at " + System.currentTimeMillis());
        pane.setLeftComponent(clickMessage);
        JButton clickMe = new JButton("Click me");
        clickMe.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                threadedIntensiveProcess(clickMessage);
//                intensiveProcess(clickMessage);
            }
        });
        pane.setRightComponent(clickMe);

        f.pack();
        f.setVisible(true);
    }

    static private void threadedIntensiveProcess(final JLabel label)
    {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("UI Thread : " + SwingUtilities.isEventDispatchThread());
                intensiveProcess(label);
            }
        }).start();
    }

    static private void intensiveProcess(JLabel label)
    {
        label.setText("was clicked at " + System.currentTimeMillis());
        for (int i = 0; i < 3; i++)
        {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            label.setText("was updated at " + System.currentTimeMillis());
        }
        System.out.println(label.getText());
    }
}
import javax.swing.*;
导入java.awt.*;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
公共类HelloButton{
公共静态void main(字符串[]args){
JFrame f=新的JFrame();
f、 setLayout(新的FlowLayout());
f、 setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
JSplitPane=新的JSplitPane();
f、 添加(窗格);
最终JLabel clickMessage=新JLabel(“在”+System.currentTimeMillis()处没有消息”);
pane.setLeftComponent(单击消息);
JButton clickMe=新JButton(“Click me”);
clickMe.addActionListener(新建ActionListener()){
@凌驾
已执行的公共无效操作(操作事件e){
threadedtensiveprocess(单击消息);
//强化过程(点击消息);
}
});
pane.setRightComponent(单击我);
f、 包装();
f、 setVisible(真);
}
静态私有void threadedtensiveProcess(最终JLabel标签)
{
新线程(newrunnable()){
@凌驾
公开募捐{
System.out.println(“UI线程:+SwingUtilities.isEventDispatchThread());
强化工艺(标签);
}
}).start();
}
静态私有void-intensiveProcess(JLabel标签)
{
label.setText(“在“+System.currentTimeMillis()处单击”);
对于(int i=0;i<3;i++)
{
试一试{
《睡眠》(2000年);
}捕捉(中断异常e1){
e1.printStackTrace();
}
label.setText(“更新于”+System.currentTimeMillis());
}
System.out.println(label.getText());
}
}

这里有两种情况需要使用
invokeLater

  • UI的创建
  • JLabel
    的更新
  • 整个UI的创建应该在EDT中完成。您可以在主线程中执行任何创建,直到
    show
    setVisible(true)
    ,因为在此之前不会出现线程问题。这是值得怀疑的;它可能会起作用——很明显,就像你的情况一样——但没有保证

    幸运的是
    JLabel
    中的
    setText
    在这种情况下表现良好。由于API不能保证该方法是线程安全的,所以您应该在EDT中调用该方法,就像调用任何其他Swing方法一样

    因此,总结一下:你有一个简单的例子,似乎是可行的-因为它很简单,你很幸运。不要依赖这些“测试”,而要依赖文档。如果您的showcase涉及代码的演示,那么您必须将调用移动到EDT以确保没有错误


    我不明白为什么您的代码不应该“保证”在最后一句话中使用
    invokeLater

    -1-在Swing中没有什么是线程安全的,除了重新绘制和重新验证:-)…这两个Swing方法是
    setText
    调用的。您有重新措辞的建议吗?保留倒数第二个状态,即
    setText
    是线程安全的;-)@《克利奥帕特拉》甚至在文章的最后明确地说明了另一个文本成分。由于方法文档不再包含此类提示,我将重新措辞。a)JLabel不是JTextComponent b)早期的文档被强烈怀疑是正确的(在一定程度上是完全错误的;-)在删除之前的下一票是为数不多的线程安全方法之一-这是错误的,确实如此:您必须将创建和对label.setText(…)的调用包装到invokeLater中,请参阅