提供一组“轻量级”(全 Java 语言)组件,尽可能在所有平台上以相同的方式工作。有关使用这些组件的程序员指南,请参阅 使用 JFC/Swing 创建 GUI,这是 The Java Tutorial 中的线索。有关其他资源,请参阅 相关文档。
Swing 的线程策略一般来说,Swing 不是线程安全的。除非另有说明,否则所有 Swing 组件和相关类都必须在事件调度线程上访问。
典型的 Swing 应用程序会响应用户手势生成的事件进行处理。例如,单击 JButton 会通知所有添加到 JButton 的 ActionListeners。由于从用户手势生成的所有事件都在事件分派线程上分派,因此大多数开发人员不会受到限制的影响。
然而,影响在于构建和显示 Swing 应用程序。对应用程序的 main 方法或 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 附加到 JTable ,则 TableModel 只能在事件调度线程上修改。如果您在单独的线程上修改模型,您将面临异常和可能的显示损坏的风险。
虽然立即更新 UI 通常是安全的,但在事件分派线程上执行时,有一个例外:如果模型监听器试图在 UI 更新以反映待定更改之前进一步更改 UI,则 UI可能会错误地呈现。如果应用程序安装的监听器需要更新 UI 以响应将导致模型结构发生变化的事件,就会发生这种情况。重要的是首先允许组件安装的监听器处理此更改,因为无法保证调用监听器的顺序。解决方案是让应用程序监听器使用 SwingUtilities.invokeLater(Runnable) 进行更改,这样对 UI 渲染的任何更改都将在处理组件安装的所有模型监听器后完成。
由于所有事件都在事件调度线程上传递,因此在事件处理中必须小心。特别是,在事件分派线程上执行的长时间运行的任务,例如网络 io 或计算密集型处理,会阻止事件分派线程分派任何其他事件。当事件调度线程被阻塞时,应用程序完全不响应用户输入。请参阅 SwingWorker ,了解在使用 Swing 时执行此类处理的首选方法。
有关此主题的更多信息,请参阅 摇摆教程,尤其是 Swing 中的并发 部分。
相关文档有关概述、教程、示例、指南和其他文档,请参阅:
Swing 连接
Java教程
Java 开发者连接处的 在线培训SM
Java Foundation Classes (JFC) 首页