5.2 AWT
AWT作为Java中最早的图形用户界面库,具有了与底层操作系统进行交互的能力。即便后来的Swing用Java自己的方式来绘制组件,也还要依赖AWT与底层操作系统进行交互。从设计的角度来说,AWT的组件库采用的是基于类继承的层次结构。每一个组件都是java.awt.Component类的对象。开发人员既可以使用AWT中的标准组件,也可以开发自己的组件。Component类中定义了操作组件的各种方法,包括常见属性(如组件的大小、位置、字体和颜色等)的获取和设置,事件监听器的处理,以及组件状态的改变等。关于这些方法的使用,通过方法名称和API文档就可以了解到具体的细节,这里不再赘述。
5.2.1 重要组件类
Component类的一个重要子类是java.awt.Container。顾名思义,Container类的对象用来包含其他AWT中的Component类的对象,是一个通用的容器。通过Container类的add和remove方法可以向容器中添加和删除组件。Component类的对象(尤其是Container类)的一个重要内部属性是该组件的有效状态。一个组件上发生与布局相关的变化之后,这个组件就会被置为无效状态。这些与布局相关的变化包括:组件的大小发生变化,Container类的对象中添加或删除了子组件。当一个组件被置为无效状态的时候,它的层次结构树上的所有祖先组件都会被置为无效状态。通过Component类的isValid方法可以检查一个组件当前是否处于有效状态。对于处于无效状态的组件,需要调用其validate方法来对包含的所有子组件重新进行布局,以恢复到有效的状态。由于validate方法会处理所有的子组件,因此一般会比较耗时。从性能的角度出发,最好对组件进行批量修改之后,再调用一次validate方法来重新布局。如果希望直接把某个组件设成无效的状态,可以使用invalidate方法。
考虑到validate方法的性能问题,Java 7把Swing中原有的有效性验证根组件(validate root)的概念扩展到了AWT中。在之前的实现中,如果一个组件被置为无效状态,那么从该组件的层次结构树向上,直到界面的顶层组件,这条路径上的所有组件都会被置为无效状态。在使用validate方法的时候要考虑所有无效的组件及其子组件,这无疑对性能影响较大。有效性验证根组件指的是某些特定类型的组件。AWT中Container类及其子类所表示的组件都可以作为有效性验证根组件。这些组件的子组件的无效状态不会影响到有效性验证根组件的父组件。也就是说,在沿着层次结构树往上设置父组件的无效状态的时候,如果发现父组件是有效性验证根组件,就不需要再把有效性验证根组件的父组件也置为无效状态了,这样就可以降低无效状态的影响范围。一个组件是否为有效性验证根组件可以通过isValidateRoot方法来判断。AWT中最常见的有效性验证根组件是java.awt.Window类。Swing中的javax.swing.JScrollPane类也是有效性验证根组件。在使用了有效性验证根组件的情况下,可以通过revalidate方法来使一个组件树快速地重新恢复到有效状态,因为revalidate会把有效性验证根组件考虑在内。不过为了与早期版本保持兼容性,有效性验证根组件并不是默认启用的,需要通过将Java系统参数“java.awt.smartInvalidate”设为“true”来启用它。在需要恢复一个组件树到有效状态的时候,开发人员应该使用revalidate方法而不是validate方法,因为revalidate方法的性能要优于validate方法。
在使用AWT的程序界面中,通常都要一个java.awt.Frame类的对象作为顶层的窗口。Frame类的作用等同于在其他程序中所看到的窗口,可以包含标题栏、边框和菜单。类java.awt.Dialog表示的是一般程序中常见的对话框,可以是模态或非模态的。Window类是Frame类和Dialog类的父类。一个Window类所表示的组件不能包含边框和菜单。在创建Window类的对象时,需要指定另外一个已有的Frame或Window类的对象作为该组件的所有者。Window类适合于创建程序中的各种不同的自定义窗口。