在 SwingUtilities.invokeLater 里面放(和不放)什么?
What to put (and not to put) inside SwingUtilities.invokeLater?
这似乎是 Swing-land 中的一种 common/good 做法,即从静态 main 方法内部调用 SwingUtilities.invokeLater(Runnable)
:
public class MyApp extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
void run() {
// What to do here?!?
}
});
// And what to do here?!?
}
}
根据该方法的 JavaDocs:
Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI. In the following example the invokeLater call queues the Runnable object doHelloWorld on the event dispatching thread and then prints a message.
但即使读完这篇文章,我仍然对在这个 Runnable
(我们通过invokeLater
),以及 not 的代码。有什么想法吗?
我觉得camickr基本解决了核心问题
为了(大部分)重复,in 进入任何可能改变 UI 或以某种方式直接或间接与 UI 交互的东西,outside 可以进入任何其他东西,尤其是任何阻塞或长 运行ning 代码
如果您看过我的任何与 Swing 相关的答案,您就会看到这种模板(是的,这是我在 Netbeans 中设置的代码模板)
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
can you give a few concrete examples?
如果它可能以任何方式改变 UI(直接或间接 - 改变组件的 属性,更新布局等)。一般的经验法则,将任何基于 Swing 的组件视为非线程安全的,你不应该有任何问题,开始第二次猜测这个规则,你将 运行 陷入困境,也许不是今天,但很可能是明天。
问题是,API 几乎无法保证某个组件何时会触发对 EDT 的更新,而这才是您真正关心的。如有疑问,请放入 EDT。
API中很少有方法被认为是线程安全的,repaint
是最明显的,但就我个人而言,我只是把整个API当作没有线程安全,省去了很多猜测。
如果你知道你有一个很长的 运行ning 或潜在的阻塞操作(文件 IO、网络调用等...),那么这些需要在 EDT 之外进行(可能使用 SwingWorker
或 Swing Timer
视情况而定),但是当您想要更新 UI (例如更改标签的文本或更新进度条)时,必须在美国东部时间的背景。
先仔细看看 Concurrency in Swing
对于未来的来者,我明白了,尽管文档并没有真正以对 Swing 新手来说显而易见的方式解释这一点:
- 当文档或 blogs/articles/people 说“Anything that touches the UI”时,这转换为:“Any manipulation of
javax.swing.*
下的秋千 class”。因此,用 JFrame
、JPanel
或任何 JComponents
做任何事情。所有这些东西都应该在您从应用程序的 main
方法内部传递给 SwingUtilities.invokeLater
的 Runnable
内部执行。所以基本上你最终会得到一个巨大的、整体的 Runnable
来完成所有 UI 代码操作。奇怪和反 MVC 恕我直言。
- 如果您有一个很长的 运行 进程,您应该从该进程中删除所有 Swing 代码并将其传递到您自己的
SwingWorker
这似乎是 Swing-land 中的一种 common/good 做法,即从静态 main 方法内部调用 SwingUtilities.invokeLater(Runnable)
:
public class MyApp extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
void run() {
// What to do here?!?
}
});
// And what to do here?!?
}
}
根据该方法的 JavaDocs:
Causes doRun.run() to be executed asynchronously on the AWT event dispatching thread. This will happen after all pending AWT events have been processed. This method should be used when an application thread needs to update the GUI. In the following example the invokeLater call queues the Runnable object doHelloWorld on the event dispatching thread and then prints a message.
但即使读完这篇文章,我仍然对在这个 Runnable
(我们通过invokeLater
),以及 not 的代码。有什么想法吗?
我觉得camickr基本解决了核心问题
为了(大部分)重复,in 进入任何可能改变 UI 或以某种方式直接或间接与 UI 交互的东西,outside 可以进入任何其他东西,尤其是任何阻塞或长 运行ning 代码
如果您看过我的任何与 Swing 相关的答案,您就会看到这种模板(是的,这是我在 Netbeans 中设置的代码模板)
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
can you give a few concrete examples?
如果它可能以任何方式改变 UI(直接或间接 - 改变组件的 属性,更新布局等)。一般的经验法则,将任何基于 Swing 的组件视为非线程安全的,你不应该有任何问题,开始第二次猜测这个规则,你将 运行 陷入困境,也许不是今天,但很可能是明天。
问题是,API 几乎无法保证某个组件何时会触发对 EDT 的更新,而这才是您真正关心的。如有疑问,请放入 EDT。
API中很少有方法被认为是线程安全的,repaint
是最明显的,但就我个人而言,我只是把整个API当作没有线程安全,省去了很多猜测。
如果你知道你有一个很长的 运行ning 或潜在的阻塞操作(文件 IO、网络调用等...),那么这些需要在 EDT 之外进行(可能使用 SwingWorker
或 Swing Timer
视情况而定),但是当您想要更新 UI (例如更改标签的文本或更新进度条)时,必须在美国东部时间的背景。
先仔细看看 Concurrency in Swing
对于未来的来者,我明白了,尽管文档并没有真正以对 Swing 新手来说显而易见的方式解释这一点:
- 当文档或 blogs/articles/people 说“Anything that touches the UI”时,这转换为:“Any manipulation of
javax.swing.*
下的秋千 class”。因此,用JFrame
、JPanel
或任何JComponents
做任何事情。所有这些东西都应该在您从应用程序的main
方法内部传递给SwingUtilities.invokeLater
的Runnable
内部执行。所以基本上你最终会得到一个巨大的、整体的Runnable
来完成所有 UI 代码操作。奇怪和反 MVC 恕我直言。 - 如果您有一个很长的 运行 进程,您应该从该进程中删除所有 Swing 代码并将其传递到您自己的
SwingWorker