我了解了swing如何不是线程安全的。深入研究,我发现对swing组件的每次修改都必须在Event Dispatch Thread上完成,以防止与多线程相关的各种问题。但是,信息似乎完全停止了。似乎没有一个好的教程可以解释如何在互联网上随处可以做到这一点。
将来自与其他问题相关的代码中的信息拼凑在一起,似乎我不得不在我的程序中的每一个swing修改中放置一个不整齐的代码块(就像我自己的代码中的这个例子):
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
setTitle("Frame title");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(800, 480);
setLocationRelativeTo(null);
setIconImage(Toolkit.getDefaultToolkit().createImage(ClassLoader.getSystemResource("Frame icon.png")));
}
});
} catch (Exception e) {
e.printStackTrace();
}
基本上,这是对的吗?我是否必须在代码中的Swing组件的每次修改周围放置该代码(或与invokeLater等效的代码)?
另外,为什么Swing不会自动执行此操作?
答案 0 :(得分:6)
诀窍是,当挥动召唤你时,它总是会在EDT中,所以你不必担心它。
但是,如果您处于计时器或由其他外部事件触发的操作,您的主线程或您创建的任何其他线程然后是,则必须使用invokeLater或invokeAndWait。
换句话说,是的,swing会自动执行“it”。需要使用invokeXx是非常罕见的,如果在内部进行摆动会浪费太多时间。
许多java程序员从来没有弄明白这一点,它可能会导致绘制GUI时出现一些非常难以发现的问题。当你不使用EDT调用它时,我确实希望swing抛出一个异常 - 如果专业GUI出现,那么Java会有更好的声誉,因为那里会有更少的废话。
答案 1 :(得分:4)
请注意,从事件处理程序执行的任何代码都已在EDT中运行(缩写中的事件)
这意味着对于一般用途(虽然你没有捣乱摇摆工作者和线程池等)你总是在EDT内部
您可以随时使用SwingUtilities.isEventDispatchThread()
另请注意,在您的代码中,对invokeAndWait
的调用将失败并在您进入EDT时抛出错误
答案 2 :(得分:3)
基本上,您不会从EDT外部绘制或更新GUI。 您从另一个线程使用SwingUtilitis.invokeLater()以确保在EDT上运行GUI绘图或更新代码。
答案 3 :(得分:3)
并非所有UI代码都必须是invokeLater调用中runnable的一部分。这只是因为你的程序的很大一部分仍然会在EDT上运行。只有在不同的线程上时才需要将消息发送到EDT。