Java 在 1995 年推出时取得的一大进步是包含了标准化的“图形用户界面”(“GUI”)库。这是一个巨大的飞跃,超越了令人眼花缭乱的不兼容第三方库,这些第三方库是以前对 GUI 开发人员开放的途径。Java GUI 库也是早使用当时全新的设计模式语言明确描述其架构的主要软件包之一。
主要包
然而,Java GUI 系统的一个令人困惑的方面是一个遗留问题,该系统在 1997 年进行了大规模升级,因此涉及的一些类分布在(相对)较旧的 java.awt包和较新的javax.swing 包中. 一般来说,如果类名以“ J ”开头,那么它在 Swing 包中。由于某些功能在 Swing 包中似乎是重复的,例如框架和按钮, 因此当有选择时,请始终使用 Swing 组件而不是较旧的 AWT 组件。
java.awt - 包含 GUI 组件的主要超类以及一些实用程序类型类,例如 Color和Point。
java.awt.event -- 包含用于管理来自 GUI 组件的事件的类和接口,例如按钮单击和鼠标移动。
javax.swing -- 包含大部分可见的 GUI 组件,例如按钮、文本字段、框架和面板。
类层次结构
Java 使用 复合设计模式来创建 GUI 组件,这些组件也可以用作容纳更多 GUI 组件的容器。这是一个 UML 图,显示了一些更常用的 GUI 组件之间的类关系:
上图中,常用的容器组件为橙色,非容器组件为蓝色。请注意,从技术上讲,所有javax.swing组件都能够容纳其他Components,但实际上,只有JFrame、 JApplet和JPanel以及上面未显示的一些(JSplitPane、JTabbedPane 和JScrollPane)通常用于此目的。
Java GUI 子系统
Java GUI 子系统由一个独立的、自动的任务执行线程组成,称为“事件循环”。每个影响 GUI 的动作,例如调用重新绘制屏幕或操作 GUI 组件的属性,或者是 GUI 发生某些事情的结果,例如用户单击鼠标或按下键,都封装在表单中放入队列中以供事件循环处理的“事件”。处理事件的结果可能是对屏幕上颜色位的操作,也可能导致调用开发人员代码中的方法。
如果我们查看处理按钮单击的过程,我们会看到用户的鼠标单击触发了一系列事件。按钮对象通过创建放置到事件队列中的按钮单击事件来响应鼠标单击。事件循环在空闲时会选择该事件并对其进行处理。按钮单击事件的处理涉及调用在专门注册的对象上的方法,这些对象称为“侦听器”,这些对象正在“侦听”单击事件。按钮单击的侦听器是实现 java.awt.ActionListener接口的对象,并且按钮单击事件处理涉及调用侦听器的actionPerformed 方法,开发人员已实现该方法以在单击该特定按钮时执行所需的任何操作。请注意,可以将多个侦听器“添加”到任何给定按钮,并且按钮单击处理将依次调用每个 ActionListener的 actionPerformed方法。
另一方面,如果我们查看绘制过程,假设开发人员的代码希望调用重新绘制屏幕上的框架组件。开发人员的代码将调用帧的 repaint()方法,但所做的只是生成一个 repaint 事件,该事件与所有其他事件一起放入事件队列中。当事件循环能够执行时,它会处理重绘事件,在此过程中,GUI 子系统将生成一个特殊的 java.awt.Graphics实例,用于表示计算机的物理屏幕。此Graphics对象作为输入参数传递给对框架的 paintComponent方法的调用。(技术上,系统调用框架的paint()方法依次调用 paintComponent(),但我们不需要担心。)由于框架是一个容器,它就像任何好的复合设计模式实现一样,依次调用 它所有子的paintComponent方法-成分。如果其中一个组件本身就是一个容器,那么绘制过程会沿着复合树向下级联,直到每个组件都有机会在屏幕上绘制自己(Graphics 对象)。开发人员可以通过简单地覆盖所需组件的paintComponent方法来插入自定义绘制操作。
常用类
简单组件
javax.swing.JLabel -- 屏幕上一段不可编辑的文本。
javax.swing.JButton -- 可以单击的按钮。单击该按钮将触发其actionPerformed 事件,该事件将调用所有已安装 ActionListener的actionPerformed 方法。
javax.swing.JTextField -- 一行用户可编辑的文本。
javax.swing.JTextArea -- 显示多行文本的框。可以设置为可编辑或不可编辑。
javax.swing.JRadioButton , javax.swing.JCheckBox -- 可以单击的小圆形或方形框以指示选择某些内容,例如某种选项。单击单选按钮或复选框将触发特定类型的事件。 可以使用名为javax.swing.ButtonGroup的不可见(对用户)类将单选按钮组合在一起,以创建一个集合,其中一次只能设置一个按钮。
javax.swing.JComboBox -- 项目的下拉列表。JComboBox 包含一组Objects而不仅仅是Strings。显示的文本是项目的toString() 方法的返回值。因此,JComboBox可用于保存任意实体,而 GUI 不知道这些实体是什么。仅当所选项目更改时才会触发事件,但始终可以检索当前所选项目及其索引。
容器组件
javax.swing.JFrame - 一个独立的“窗口”或“框架”,带有标题和通常的移动、调整大小、小化、大化和关闭功能。对于大多数人来说,这是他们系统中的容器。因此,一个JFrame不能容纳另一个JFrame。虽然 JFrame可以包含任何类型的组件,但通常,JFrame包含 JPanels,它们被安排为将窗口(框架)中使用的组件集组合在一起。JFrame的默认布局管理器是 BorderLayout。JFrame有 几个独特而重要的方法值得指出:
void getContentPane().add(Component c) -- 向框架添加一个组件。请注意, 这里JFrame的行为与JPanel略有不同 ,因为 JFrame有一个很少使用的功能,即多层(窗格)组件可以切换到可见性和不可见性。 从java.awt.Container继承的此方法有一些重写形式,允许传递布局管理器的参数,例如组件在 BorderLayout中的位置。
void setDefaultCloseOperation(int option) -- 设置框架关闭时的行为。请参阅有关关闭 JFrame 时设置行为的网页。
javax.swing.JApplet -- 允许 Java 程序作为网页中的组件运行。请注意,applet 和框架不是同一事物并且不可互换,尽管有一些解决方法允许相同的代码作为独立应用程序或网页中的 applet 运行。
javax.swing.JPanel -- 用于在框架中或其他面板内部布置组件的基本构建块。一个 JAva GUI 由一个框架和一个面板组成,面板包含面板,等等。请注意,这里的“面板”也可以是滚动窗格、拆分窗格和/或选项卡式窗格(见下文)。JPanel的默认布局管理器 是FlowLayout。
javax.swing.JScrollPane -- 允许您显示单个面板,其侧面带有滚动条,允许显示比屏幕上容纳的更多或更大的组件。
javax.swing.JSplitPane -- 允许显示两个面板,使用垂直或水平的用户可移动条将它们分开。
javax.swing.JTabbedPane -- 允许以“选项卡式”格式显示多个面板。