1、JComponent类概览
JComponent扩展java. awt.Container,而 java. awt . Container又扩展java.awt . Component,因此,所有的Swing组件都是AWT容器。Component 和Container类本身提供了大量的功能,因此,JComponent继承了大量的功能。
因为JComponent为几乎所有的Swing组件提供下层构件,因此,它是一个很大的类,包括100多个public方法。JComponent类为它的扩展提供了下面的功能:
- **边框:**任何JComponent 的扩展都可以带边框。Swing 提供了许多不同风格的边框,如雕刻边框、带标题边框和蚀刻边框。虽然一个组件只能有一个边框,但是边框是可以组合的。因此,从效果上来看,单个组件可有多个边框。
- 自动滚动: 当把光标拖出了组件的边界时,Swing轻量组件可以滚动其内容,这个特性称作自动滚动。所有的JComponent扩展都继承了自动滚动的功能。可以在每个组件的基础上设置允许或禁止自动滚动。缺省时,JList和JI able是允许自动滚动的。
- **可访问性:**可访问性是使人人都能使用软件。例如,为视力不好的用户放大字体或为听力不好的用户显示带声音的标题。
Swing 的插入式界面样式体系结构通过允许把可选择的界面样式分配给一组组件来支持可访问性。 - **工具提示:**工具提示是当光标停在带工具提示的JCmpnext扩展上时,在一个小窗口中显示的字符串。工具提示大多用在工具条按钮上,用于描述指定按钮的功能。
工具提示相当灵活,例如,可根据停留在组件上的光标位置来改变工具提示的文本内容。图像映像是需要这种特性的主要情况,图像映像弹出对当前光标下的内容的简单说明。
可通过ToolTipManager类来设置从光标开始停留在组件上到显示工具提示之间的时间间隔。 - **双缓存:**在更新组件(擦除然后重绘组件)时,会产生可察觉的闪烁。双缓存通过在屏外缓存区中更新组件,然后把屏外缓存区的相应部分拷贝到组件的屏上代表中来消除闪烁。
所有的Swing轻量组件都继承了双缓存它们显示内容的能力。一个屏外缓存(由Swing 的RepaintManger维护)常用于双缓存JComponent的扩展。 - 调试图形: 调用JComponent.setDebugGraphicsOptions (int)可以把一个组件转换成一个慢速绘制器,该绘制器在每个图形调用前闪烁一下,而且还可以维护-个图形调用的日志文件。
调试图形允许开发人员快速、准确地了解组件是如何绘制的,在实现一个需要大量绘制的定制组件时,调试图形是很方便的。 - **键击处理:**JComponent类提供对嵌套键击处理的支持。不需要开发人员过滤所有的键击事件并对感兴趣的键击事件作出反应,当在某些条件下按下或释放一个键击时,可以指示JComponent 把动作事件发送给一个特定的目标。
- 客户属性: 每个JComponent对象都维护一个称作客户属性的词典。词典维护一组“关键字/值”对,“关键字/值"对可以是任何类型的对象。客户属性可以把任何JComponent与一个不扩展JComponent类的对象联系起来。
2、JComponent类结构
2.1 Swing组件是AWT容器
因为JComponent扩展java. awt . Container,所以每个JComponent 扩展都可以包含AWT和Swing组件。
2.2 最小尺寸、最大尺寸和首选尺寸
我们要对上面这句话进行解释,一个组件的最小尺寸、最大尺寸和首选尺寸并不决定其实际尺寸。通常,布局管理器设置组件的大小,且布局管理器有权决定是否使用最小尺寸、最大尺寸和首选尺寸。事实上,最小尺寸、最大尺寸和首选尺寸是一个尺寸请求,在确定组件尺寸时,该请求可能被考虑也可能不被考虑。
与AWT组件必须扩展才能修改最小尺寸、最大尺寸和首选尺寸不同,Swing 组件带有设置组件尺寸的方法。
void setMaxmumSize(Dimension) //设置组件最大尺寸
void setMinimumSize(Dimension) //设置组件最小尺寸
void setPreferredSize(Dimension) //设置组件首选尺寸
Dimension getMaxmumSize() //返回组件的最大尺寸
Dimension getMinimumSize() //返回组件的最大尺寸
Dimension getPreferredSize() //返回组件的最大尺寸
3、绘制JComponent组件
3.1. paint、repaint和update方法
- 调用repaint ()后,就会调用AWT组件和Swing 组件的update方法。
- 对AWT组件,update()擦除该组件的背景,接着调用paint ()。有时,擦除背景是人们所不希望的。例如,在一个图形条中,不断用获得的新数据来更新其显示。反复擦除和重新绘制该图像会导致可察觉的闪烁。在这种情况下,一般是用AWT组件的扩展来重载update()以便直接调用paint()方法,因此,避免了擦除组件背景和与之有关的闪烁。
- 对Swing 组件而言,为了消除闪烁,不需要重载update ()来直接调用paint ()。因为,JComponent类重载了update (),直接调用paint ()。然而,这不是说Swing组件在重新绘制组件时不擦除组件背景。当重新绘制Swing组件时,擦除这个组件背景的任务就交给这个组件的UI代表来完成(如果这个组件有一个UI代表的话)。
- 幸运的是,不需要子类化一个组件的UI代表来消除闪烁,因为,缺省时,Swing组件是双缓存的,这意味着擦除组件然后重新绘制组件的工作都是在屏外缓存中进行的。当组件在其屏外缓存中更新后,再把更新后的组件拷贝到屏幕上。双缓存消除了闪烁,因此,不需要为Swing 组件重载update()方法。如果Swing 组件闪烁,则解决方法是确保该组件是双缓存而不是重载update ( )。
3.2 validate、invalidate和revalidate
Swing 和AWT的containers都提供了一个validate方法,该方法可为容器中的所有组件布局。例如,有一个容器,它含有一个按钮,且这个按钮的文本已经改变(因此是无效的),如果为该容器调用validate (),则该容器将布局这个按钮及该容器中的所有其他组件。
对invalidate ()和validate ()的调用在容器层次结构中分别向上和向下传播,因此,使一个组件无效会使这个组件的容器层次结构中的所有容器无效。
JComponent类提供了–个revalidate方法,这个方法使组件无效并为组件层次结构中的第一个容器在事件派发线程上安排一个validate ()的调用,如果组件的isValidateRoot 属性被设置为true的话。因为包含在JApplet或JFrame实例中的所有Swing组件都在根面板中,所以,为Swing小应用程序或应用程序中的一-个Swing组件调用revalidate ()将使该组件被布局。在组件布局后,已改变的组件区域将重新绘制。
注意:
第一,同调用repaint ()一样,对revalidate ()的调用是合并的。因此,如果为某个容器中的多个组件连续调用revalidate (),则这些revalidate ()调用将合并,即只调用一次revalidate ( )。
第二,任何为改变位置和大小而改变的Swing 组件应该通过组件本身来重新生效,布局和重新绘制组件。不幸的是,对Swing 1.1 FCS/1.2 JDK,重新生效操作并不总是执行。如果在组件的位置和大小改变后,组件没有被布局和重新绘制,则这是Swing 的错误造成的。
第三,虽然对JComponent . revalidate()的调用应该使已经变化了的组件域重新绘制,但是重新绘制不总是发生。因此,有时需要在调用revalidate ()后,再调用repaint ( )。
3.3 不透明组件与透明组件的比较
Swing组件可以是不透明的或部分透明的。
3.4 立即绘制Swing组件
为一个组件调用repaint ()会产生一个将要放到AWT事件序列上的绘制事件。因此,如果repaint ()是从一个事件处理方法中调用的,则直到该事件处理方法返回才会进行重新绘制。
JComponent类提供了立即绘制组件的方法,即 paintImmediately ()方法,该方法适合在需要立即更新组件外观的事件处理方法中使用。
4、双缓存
Swing包括一个RepaintManager类,该类维护一个屏外缓存。该缓存很大,足以容纳下屏幕的大小,用它来双缓存所有的Swing 轻量组件。如果一个组件处在一个双缓存的容器中,则该组件就自动是双缓存的,因此,对Swing的轻量容器来说,缺省时,只需规定JRootPane和JPanel是双缓存的即可。
5、调试图形
Swing
提供了java. awt.Graphics
类的一个扩展——swing. DebugGraphics
,它减慢图形操作的速率并且在每次操作前闪烁。另外,DebugGraphics
类可以输出它所执行的图形调用的日志。操作执行的速率、每次操作的闪烁次数、闪烁的颜色和要输出的日志流都是可设置的,可通过DebugGraphics类中的static public方法来设置。
在利用调试图形方面,现在我们所知道的要比我们实际所需要的多。与大多数Swing特性一样,调试图形已不再复杂,例如,我们不需要知道还有一个扩展java .awt.Graphics 的 DebugGraphics类。要使用调试图形,只需调用JComponent的方法 setDebugGraphicsOptions ( int),其中的整数参数代表下面的调试选项:
DebugGraphics. LOG _ OPTION
DebugGraphics.FLASH _ OPTION
DebugGraphics. BUFFERED _ OPTION
DebugGraphics . NONE_ OPTION
把Swing组件的调试图形选项设置为DebugGraphics.NONE_ OPTION 以外的任意选项,都会引起该组件在绘制时使用一个DebugGraphics实例。
选项 BUFFERED_ OPTION用于双缓存组件,它引起弹出一个外部的窗口并显示该组件的屏外缓存。
6、自动滚动
JComponent具有自动滚动的功能。当鼠标被拖出组件的边界后,自动滚动功能使组件能继续滚动。
调用JComponent的 setAutoScrolls ( boolean)方法可启用或禁用自动滚动。JComponent还提供返回一个boolean值的 getAutoscrolls方法,该boolean值指示该组件的自动滚动是否是允许的.缺省时,只有列表和表格的自动滚动是允许的。
7、工具提示
工具提示是当鼠标停留在一个组件上的时间超出指定的时间后在一个窗口中显示的一行文字。
把工具提示与一个Swing 组件相关联是通过调用JComponent.setToolTiplext()来实现的。JComponent.setToolTiplext()所带的参数是将在工具提示窗口中显示的字符串。把null字符串传送给setToolTiplext()将使该组件以前的工具提示无效。
7.1基于鼠标位置的工具提示
在工具提示的实现上,有三个类:
- 第一是JComponent类,如前所述,JComponent类提供了一个setTooTipText方法,该方法为组件激活工具提示并设置与工具提示有关的文本。
- 第二是JToolTip类,由于Swing插入式界面样式的实现,这个类仅维护工具提示文本和一个对与工具提示有关的组件的引用。实际显示工具提示文本的代码封装在工具提示的界面样式中,而界面样式又存在于swing . plaf . ToolTipUI类的扩展中。
- 第三,Swing的ToolTipManager类负责提供一个将在其中显示工具提示的窗口,并负责把JTooTips 实例插入到显示它们的窗口中。ToolTipManager还控制定时问题,如鼠标停留在组件上的时间与显示工具提示的时间之间的时间差。
7.2 工具提示的首选位置
重载JComponent . getToolTipLocation方法可以用来设置工具提示的首选位置。getToolTipLocation方法带入一个MouseEvent并返回一个 Point,工具提示将显示在 Point 的位置上。
缺省时,JComponent . getrToolTipLocation ()返回null,指示工具提示应该直接显示在鼠标光标的下面。
JComponent 的扩展可以重载getToolTipText ()来指定要显示的工具提示的确切位置。
7.3 定制工具提示的行为
当光标在组件上停留一定时间后就会显示工具提示,这里的一定时间指的是初始延迟。缺省时,初始延迟被设置为750毫秒。
下述三个事件之一的事件可清除工具提示:
- 光标离开了这个组件。
- 按下了鼠标。
- 清除延迟:指的是提示从出现到消失的时间
如果光标离开显示工具提示的组件,接着进入另一个带工具提示的组件,则第二个组件的工具提示可能立即显示出来。如果退出第一个组件进入第二个组件之间的时间少于重新显示延迟( reshow delay),则第二个组件的工具提示将会立即显示。缺省的重新显示延迟时间是500毫秒。表4-3总结了工具提示的延迟。
7.4 定制工具提示的界面样式
与大多数Swing组件一样,工具提示也有一个UI代表,该UI代表决定该工具提示的界面样式。
8、键击处理
当向一个特定的组件登记了键击时,这个组件就称作已登记的组件。处理一个键击指的是与这个键击相关联的ActionListener调用其actionPerformed方法。
当已登记的组件有焦点时,处理满足WHEN_ FOCUSED条件的键击。
当已登记的组件有焦点或已登记的组件包含有焦点的组件时,则处理满足WHEN_ ANCES-TOR_ OF _ FOCUSED _ COMPONENT条件的键击。对键击处理而言,术语父组件指容器包含层次结构,而不是继承关系。从这个意义上讲,父组件与容器是同义的。
当任何与已登记组件处在同一个窗口中的组件有焦点时,处理WHEN_ IN_ FOCUSED _ WINDOW键击。
9、客户属性
每个JComponent实例都维护-个称作客户属性的属性字典。一个字典由一-组键/值对组成,这里,键和值可能是任何类型的对象。Swing类本身使用客户属性。例如,组件把它们的工具提示文本作:为一个客户属性来维护,JL ayeredPane类把它的组件层作为–个客户属性来维护。
客户属性是被约束的属性,即不论何时一个客户属性修改了,那么属性变化事件就会发送给组件的属性变化监听器。
处理客户属性的方法:set/getClientProperty()
10、焦点管理
缺省时,在 Swing容器中按下Tab键将把焦点移到下一个可获得焦点的组件上,按下Shift+Tab可把焦点移到上一次获得焦点的组件.上。可以用JComponent的焦点属性或缺省焦点管理器的替代属性来修改缺省的行为。
10.1 JComponent的焦点属性
- focusCycleRoot——确定一个容器是否包含形成它们自己的焦点循环的那些组件。如果该属性设置为true,则按下Tab键将把焦点移到该容器中并且焦点会在容器的组件中移动,但不会移出容器本身。
- focusTraversable—-—确定焦点管理器是否将把焦点传给一个组件。其focusTraversable属性指定为false 的组件在requestFocus ()被调用时仍将接受焦点,例如,如果一个按钮的focusTraversable属性被设置为false(通过在JButton 的一个扩展中重载isFocusTraversable ( )),则单击该按钮会产生对requestFocus ()的一个调用,并且该按钮仍将接受焦点。但是,如果按下Tab或Shift + Tab,则该按钮将不接受焦点。
- managingFocus——确定当按下键把焦点切换到–个组件或从一个组件把焦点移开时,是否要把所按下的键传送给这个组件本身。缺省时是不传送的。
- requestFocusEnabled——与focusTraversable属性相反,如果该属性设置为false,则在request-Focus ()调用时组件将不接受焦点,但是,作为键按下的结果,焦点管理器将把焦点传给该组件。
- nextFocusableComponent——在按下Tab键时,指定接受焦点的下一个组件。注意,不能把焦点传送给以前的可获得焦点的组件。
10.2 焦点管理器
- Swing的焦点管理器负责把焦点从一个组件传送给另一个组件。Swing 提供了一个抽象的FocusManager类和一个DefaultFocusManager 扩展。DefaultFocusManager类把焦点从左传送到右,从上传送到下。
- 缺省的焦点管理器负责确定用哪个键来移动焦点。缺省时,Tab和Ctrl +'Tab向前移动焦点,Shift +Tab和 Ctrl + Shift +Tab向后移动焦点。可以扩展DefaultFocusManager,而且可以重载其processKeyEvent方法以便修改缺省的行为。
- 假如当前有焦点的组件没有重载getNextFocusedComponent()来返回一个非空组件,则缺省焦点管理器在comparelabOrder方法的帮助下将决定哪个组件下一次将接受焦点。DefaultFocusMan-ager. compareTabOnder 以两个组件为参数并返回一个boolean值,该值指出在tab顺序中它的第一个组件参数是否在第二个组件参数前。