模块  java.desktop

Package javax.swing

提供一组“轻量级”(全Java语言)组件,这些组件在所有平台上尽可能地工作。 有关使用这些组件的程序员指南,请参阅“Java教程” Creating a GUI with JFC/Swing 有关其他资源,请参阅Related Documentation

Swing's Threading Policy

一般来说,Swing不是线程安全的。 除非另有说明,否则必须在事件派发线程上访问所有Swing组件和相关类。

典型的Swing应用程序响应于从用户手势生成的事件进行处理。 例如,点击一个JButton通知所有ActionListeners添加到JButton 由于在事件调度线程上调度了从用户手势生成的所有事件,因此大多数开发人员不受限制的影响。

然而,影响在于构建和显示Swing应用程序。 调用应用程序的main方法,或方法Applet ,没有事件调度线程上调用。 因此,在构造和显示应用程序或applet时,必须注意将控制转移到事件调度线程。 转移控制并开始使用Swing的首选方法是使用invokeLater invokeLater方法安排在事件分派线程上处理Runnable 以下两个示例同样适用于传输控制和启动Swing应用程序:

  import javax.swing.SwingUtilities; public class MyApp implements Runnable {     public void run() {         // Invoked on the event dispatching thread.         // Construct and show GUI.     }     public static void main(String[] args) {         SwingUtilities.invokeLater(new MyApp());     } } 
要么:
  import javax.swing.SwingUtilities; public class MyApp {     MyApp(String[] args) {         // Invoked on the event dispatching thread.         // Do any initialization here.     }     public void show() {         // Show the UI.     }     public static void main(final String[] args) {         // Schedule a job for the event-dispatching thread:         // creating and showing this application's GUI.         SwingUtilities.invokeLater(new Runnable() {             public void run() {                 new MyApp(args).show();             }         });     } } 
此限制也适用于附加到Swing组件的模型。 例如,如果TableModel附加到JTableTableModel应在事件指派线程上修改TableModel 如果在单独的线程上修改模型,则存在异常和可能的显示损坏的风险。

虽然立即对UI进行更新通常是安全的,但在事件分派线程上执行时,有一个例外:如果模型侦听器在UI更新之前尝试进一步更改UI以反映挂起的更改,那么UI可能会渲染错误。 如果安装了应用程序的应用程序需要更新UI以响应将导致模型结构发生更改的事件,则会发生这种情况。 首先允许组件安装的侦听器处理此更改非常重要,因为无法保证可以调用侦听器的顺序。 解决方案是让应用程序侦听器使用SwingUtilities.invokeLater更改,以便在处理组件安装的所有模型侦听器之后对UI呈现进行任何更改。

由于所有事件都在事件调度线程上传递,因此必须注意事件处理。 特别是,在事件调度线程上执行的长时间运行的任务(例如网络io或计算密集型处理)阻止事件调度线程调度任何其他事件。 当事件调度线程被阻止时,应用程序完全没有响应用户输入。 有关使用Swing时执行此类处理的首选方法,请参阅SwingWorker

有关该主题的更多信息,请参见Swing tutorial ,特别是Concurrency in Swing

Related Documentation

有关概述,教程,示例,指南和其他文档,请参阅: