(swing读书笔记)Insets/Border/Icon/Action

 

Insets/Border/Icon/Action

                                                      

在比较AWT、SWING的不同之处时,InSets和Border是个有趣的话题。

 

InSets是AWT时代就有的概念,多译为“边衬”,是指容器的边衬部分,布局管理器在安置容器的组件时,不会占用inSets部分。而且,AWT不提供动态改变inSets大小的方法,只提供getInsets()供子类型重载,即如想改变容器的inSets,只能继承该类,并重载该方法。

 

而Border是Swing引入的概念。Border绘制在inSets内——可以简单的理解成Border会占据整个InSets空间,事实上getInsets已经被重载以返回其Border的“边衬”(即返回Border接口的getBorderInsets方法的返回值)。通过动态的为Component设置Border(通过setBorder方法),就可以改变Component的inSets的大小。因此,Swing时代,基本上已经不再重载getInsets方法了——如果使用空Border(EmptyBorder),就可以得到“传统意义”上的InSets。

 

只所以会有如此奇怪的设置,我猜测原因是这样的。

AWT中的容器多是重量的,即有其相应的同位体。容器本身的绘制是由其同位体完成的,同位体有自身的Border,而inSets的引入也是为了腾出绘制Border位置。AWT其实是不鼓励改变InSets大小的,因为如果设置太小的InSets,组件有可能占据组件Border的位置。又由于Border的绘制是由同位体负责的,AWT就没有理由引入Border的概念了。

 

Swing的情况完全不同。所有的Swing组件(Swing组件都是容器)都是轻量的,它们由Swing负责绘制——包括容器的Border。因此,Swing可控制Border的绘制,Border类的引入就顺理成章了。

 

Border不是组件,只是组件用来委托绘制“边框”而已,所以不同的组件当然可以共享一个Border对象作为委托对象。BorderFactory被引入,尽量应该使用“工厂”来生产Border对象——对于能够共享的Border对象,“工厂”被实现成singleton模式——我们只管为每个Component创建Border即可,优化的工作就交给工厂来完成吧。

 

Border接口有3个方法:

(1)         isBorderOpaque();

(2)         paintBorder(Component , Graphics, int, int, int, int );

(3)         getBorderInsets(Component)

 

AbstractBorder是顶层的Border类实现,正如它名字所示,它是个Abstract类。如要实现自己的Border,则需要继承AbstractBorder类——通常需要重载paintBorder和getBorderInsets——AbstractBorder不绘制边框,会返回一个(0,0,0,0)的Insets。

 

需要注意的是,某些组件拥有默认的Border,有些Border还帮助组件实现特定的界面样式。当更改这些组件的Border时,需要特别小心。

Icon

Icon的概念与Border及其相似,它们都不是Component,但都被Component用来委托绘制一些东西——不同的是,Border绘制在Insets中,而Icon绘制在Component的非Insets部分。

 

同Border不同,Component并没有类似setIcon方法——支持Icon的Component通常会添加一个使用Icon作为参数的构造函数。

 

所有的Icon都实现Icon接口:

 int

getIconHeight()
          返回图标的高度。

 int

getIconWidth()
          返回图标的宽度。

 void

paintIcon(Component c,Graphics g, int x, int y)
          在指定位置上绘制图标。

 

最常用的Icon实现是IamgeIcon类,IamgeIcon内部使用MediaTracker的一个实例来完全装载image。如果装载失败,其后调用paintIcon()将不会有任何操作,而getIconHeight()、getIconWidth()会返回-1。

 

有大量的Swing组件支持Icon——这很容易理解,因为Swing完全控制Component的绘制,它当然可以在Component上绘制一个Icon。

Action

与Icon相比,Action不太好理解,JDK帮助文档对Action接口的描述如下:

Action 接口提供 ActionListener 接口的一个有用扩展,以便若干控件访问相同的功能。

除了 ActionListener 接口定义的 actionPerformed 方法之外,此接口还允许应用程序在一个位置定义:

  • 描述函数的一个或多个文本字符串。这些字符串可用于显示按钮的立体文本、在菜单项中设置文本等等。
  • 描述函数的一个或多个图标。这些图标可用于菜单控件中的图像,或者用于更复杂用户界面中的合成项。
  • 功能的启用/禁用状态。应用程序可以禁用实现此接口的函数,而不必分别禁用菜单项和工具栏按钮。所有为侦听状态更改而注册为侦听器的组件都将禁止为该项生成事件,并相应地修改显示。

 

而AbstractAction是Swing提供的实现了Action接口的抽象基类,供用户继承——你必须自行实现actionPerformed方法。

 

我们看一个例子:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
 
public class Test extends JApplet {
          public void init() {
                    JMenuBar mb = new JMenuBar();
                    JMenu fileMenu = new JMenu("File");
 
                    fileMenu.add(new ExitAction());
                    mb.add(fileMenu);
                    setJMenuBar(mb);
          }
}
class ExitAction extends AbstractAction {
          public ExitAction() {
                    super("exit");
          }
          public void actionPerformed(ActionEvent e) {
                    System.exit(0);
          }
}

 

显然,我们并没有为菜单项设置String(我们甚至没有去创建菜单项)——菜单项自动获取了Action的String;如果Action带有Icon,菜单项还可以获取这个Icon。

 

除了String、Icon之外,Action还有一个状态值,当带有状态特征的Component使用该Action后,也会以此状态作为自己的状态(如按钮就带有状态),以下方法用于设置、获取Action的状态。

 boolean

isEnabled()
          返回 Action 的启用状态。

 void

setEnabled(boolean b)
          设置 Action 的启用状态。

 

Action还定义了一些列的常量作为Key值,可以通过这些常量进行获取、设置,如:

static String

NAME
          用来存储动作的 String 名称的键,用于菜单或按钮。

          (即上例中,显示在菜单上的“String”)

static String

SMALL_ICON

         即可以显示在菜单上的“Icon”

 Object

getValue(String key)
          使用关联的键获取此对象的一个属性。

 void

putValue(String key,Object value)
          使用关联的键设置此对象的一个属性。

这样,就可以动态的修改Action的这些信息——事实上,Component也是通过这些方法来获取自己需要的信息的。

 

还有一点需要注意的是,任何Action的属性修改后,都会激发属性修改事件,当然Action接口提供了相应的方法来添加、去除Listener:

 void

addPropertyChangeListener(PropertyChangeListener listener)
          添加一个 PropertyChange 侦听器。

 void

removePropertyChangeListener(PropertyChangeListener listener)
          移除一个 PropertyChange 侦听器。

 

同Icon、Border一样,Action也能被多个组件共享,共享Action的Component会具有同样的属性——来自Action。

 总结

Border、Icon和Action都有两个共同特点:

(1)         它们都不是组件;

(2)         多个组件可以共享它们。

 

为多个组件共享不近节省了资源,还提供了一致性。对Action而言,还为GUI提供了控制中心点。

你可能感兴趣的:(swing,String,读书,action,import,border)