Java 在SwingUtilities.invokeLater中放置(和不放置)什么?
在Swing land中,从静态主方法内部调用Java 在SwingUtilities.invokeLater中放置(和不放置)什么?,java,multithreading,swing,awt,Java,Multithreading,Swing,Awt,在Swing land中,从静态主方法内部调用SwingUtilities.invokeLater(Runnable)似乎是一种常见/良好的做法: public class MyApp extends JFrame { public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override void run(
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?!?
}
}
根据该方法的:
导致在AWT事件调度线程上异步执行doRun.run()。这将在处理完所有挂起的AWT事件后发生。当应用程序线程需要更新GUI时,应使用此方法。在下面的示例中,调用器调用将事件调度线程上的可运行对象doHelloWorld排队,然后打印一条消息
但即使在阅读了本文之后,我仍然不知道应该(特别是)在这个
可运行的(我们传递给invokeLater
)中放什么代码,以及不应该放什么代码。有什么想法吗?
我认为camickr基本上解决了核心问题
为了(大多数情况下)重新迭代,in可以加入任何可能改变UI或以某种方式直接或间接与UI交互的内容,外部可以加入任何其他内容,尤其是任何阻塞或长时间运行的代码
如果您看过我的任何与Swing相关的答案,您都会看到这种模板(是的,这是我在Netbeans中设置的代码模板)
你能举几个具体的例子吗
如果它可能以任何方式改变UI(直接或间接-更改组件的属性、更新布局等)。一般的经验法则是,将任何基于Swing的组件视为非线程安全的组件,并且您不应该有任何问题,如果开始对这条规则进行二次猜测,您将遇到麻烦,可能不是今天,但很可能是明天
问题是,API中很少保证组件何时会触发EDT更新,这正是您真正关心的。如有疑问,请填写EDT
API中很少有被认为是线程安全的方法,repaint
是最明显的,但就我个人而言,我只是将整个API视为线程不安全的,这避免了很多猜测
如果您知道您有一个长时间运行的或潜在的阻塞操作(文件IO、网络调用等),那么这些操作需要在EDT之外进行(可能使用SwingWorker
或Swing计时器
,视情况而定),但在您想要更新UI时(例如更改标签文本或更新进度条),这些调用必须在EDT的上下文中进行
首先仔细看看我认为camickr基本上解决了核心问题 为了(大多数情况下)重新迭代,in可以加入任何可能改变UI或以某种方式直接或间接与UI交互的内容,外部可以加入任何其他内容,尤其是任何阻塞或长时间运行的代码 如果您看过我的任何与Swing相关的答案,您都会看到这种模板(是的,这是我在Netbeans中设置的代码模板) 你能举几个具体的例子吗 如果它可能以任何方式改变UI(直接或间接-更改组件的属性、更新布局等)。一般的经验法则是,将任何基于Swing的组件视为非线程安全的组件,并且您不应该有任何问题,如果开始对这条规则进行二次猜测,您将遇到麻烦,可能不是今天,但很可能是明天 问题是,API中很少保证组件何时会触发EDT更新,这正是您真正关心的。如有疑问,请填写EDT API中很少有被认为是线程安全的方法,
repaint
是最明显的,但就我个人而言,我只是将整个API视为线程不安全的,这避免了很多猜测
如果您知道您有一个长时间运行的或潜在的阻塞操作(文件IO、网络调用等),那么这些操作需要在EDT之外进行(可能使用SwingWorker
或Swing计时器
,视情况而定),但在您想要更新UI时(例如更改标签文本或更新进度条),这些调用必须在EDT的上下文中进行
首先,让我们更仔细地了解一下未来的新来者,我发现了这一点,尽管文档并没有以一种对摇摆新手来说显而易见的方式来解释这一点:
- 当文档或博客/文章/人说“任何涉及UI的内容”时,这就转化为:“在
下对Swing类的任何操作”。因此,使用javax.Swing.
、JFrame
或任何JPanel
执行任何操作。所有这些内容都应该在应用程序的JComponents
方法中传递给main
的SwingUtilities.invokeLater
中执行。因此,基本上你最终得到了一个巨大的、单片的Runnable
,它完成了所有的UI代码操作。奇怪的和反MVC的IMHORunnable
- 如果您有一个长时间运行的流程,您应该将所有Swing代码从该流程中剥离出来,并将其传递给您自己的
SwingWorker
- 当文档或博客/文章/人说“任何涉及UI的内容”时,这就转化为:“在
下对Swing类的任何操作”。因此,使用javax.Swing.
、JFrame
或任何JPanel
执行任何操作。所有这些内容都应该在应用程序的JComponents
方法中传递给main
的SwingUtilities.invokeLater
中执行。因此,基本上你最终得到了一个巨大的、单片的Runnable
,它完成了所有的UI代码操作。奇怪的和反MVC的IMHORunnable
- 如果您有一个长时间运行的进程,那么您应该将所有Swing代码从该进程中剥离出来,并将其传递到您自己的
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); } }); } }