我在某处读到,对于影响 gui 视觉效果的任何线程,它应该使用 SwingUtilities.invokeAndWait/invokeLater 在 EDT 中运行
new SwingGUI().setVisible(true);
对于基本的 gui,是否有必要使用 invokeAndWait 在 EDT 行中添加类似内容?只是为了展示?
这算不算?
我在某处读到,对于影响 gui 视觉效果的任何线程,它应该使用 SwingUtilities.invokeAndWait/invokeLater 在 EDT 中运行
new SwingGUI().setVisible(true);
对于基本的 gui,是否有必要使用 invokeAndWait 在 EDT 行中添加类似内容?只是为了展示?
这算不算?
对您的问题的简短回答是:是的,即使呼叫setVisible
也应该发生在 EDT。判断当前线程是否为EDT,可以使用EventQueue#isDispatchThread
方法
一些参考链接:
编辑:阅读我提供的链接后,Oracle 网站上的一些文章似乎已经过时,因为它们仍然记录您可以在另一个线程上创建 Swing 组件。对此有一个stackoverflow问题,其中包含一些不错的答案以及有关“新”政策的博客文章和文章的链接(几年前的新政策)
是的,如果您触摸 Swing 对象,则必须在 EDT 上进行。在大多数情况下,您已经在那里,但如果没有,请使用这些SwingUtilities
类。这样做的原因是 Swing 类不是多线程的,所以如果你在其他线程上访问它,很可能会导致令人讨厌的问题。可能是setVisible()
在幕后做了很多事情来展示一些东西(比如重新布置东西)。最好是安全的。
从您的电话中调用的任何内容
public static void main(String[] agrs) {
直接(不产生另一个线程或使用invokeLater)在主线程上运行。
当 EDT(由用户输入触发)可能(同时)访问主线程时使用主线程访问 GUI 对象可能会导致线程问题。调用 invokeLater 会导致任务(runnables)在 EDT 上运行,防止其他 EDT 任务同时访问,即。按钮按下等
如果您可以确定 EDT 不忙(在第一个窗口 setVisible(true) 之前),您可以从主线程访问 GUI。如果您可以确定 EDT 没有引用您正在处理的组件(它超出了 EDT 的范围),即。在它被添加到任何容器之前,您可以从主线程访问它,而 EDT 不会同时访问它,因为 EDT 无法访问它。
Everything that access Swing objects should do so via the Event Dispatch Thread (EDT). There is one small exception to this (which I'll mention later). The purpose of the EDT is to process any events that may occur due to IO (mouse and keyboard events). Quite a lot of the time this can mean altering the layout of your GUI. Swing was not developed to be thread-safe, meaning that that if two thread try to modify the same component at the same time then you can end up with a corrupted GUI. Since there is already one known thread to be accessing Swing components (the EDT), no other thread should attempt to modify them or even read their state.
Now, to the exceptional case when you can manipulate Swing objects outside of the EDT. Before any components have become visible it is not possible for IO to be triggering events. Therefore, the main thread can setup a Swing GUI and then set a single JFrame to be visible. Since there is now a visible frame IO events can occur and the main thread should not try to modify any more Swing components. The should only use this option to get a GUI started, and really only with toy problems.
What I'm saying is that the following is fine and won't cause problems if you're just playing around with stuff.
public static void main(String[] args) {
// create components
JFrame f = new JFrame();
...
// do layout and other bits of setup
// show gui to user
f.setVisible(true);
}