如图4-1所示,AbstractButton类是作用在幕后作为所用 的Swing按钮组件的一个重要Swing类。在本章稍后的JButton类中所描述的JButton是最简单的子类。其余的子类将会在后续的章节中进行描述。
所有的AbstractButton子类使用ButtonModel接口来存储数据模型。DefaultButtonModel类是所使用的默认实现。另外,我们可以将任意的AbstractButton对象组合为一个ButtonGroup。尽管这种组合对于JRadioButton与JRadioButtonMenuItem组件最为自然,然而任意的AbstractButton子类都会起作用。
表4-11列出了AbstractButton子类所共享的32个属性。这些属性可以使得我们自定义所有按钮的外观。
属性名 | 数据类型 | 访问性 |
action | Action | 读写绑定 |
actionCommand | String | 读写 |
actionListeners | ActionListener[] | 只读 |
borderPainted | boolean | 读写绑定 |
changeListeners | ChangeListener[] | 只读 |
contentAreaFilled | boolean | 读写绑定 |
disabledIcon | Icon | 读写绑定 |
disabledSelectedIcon | Icon | 读写绑定 |
disabledMnemonicIndex | int | 读写绑定 |
enabled | boolean | 只写 |
focusPainted | boolean | 读写绑定 |
horizontalAlignment | int | 读写绑定 |
horizontalTextPosition | int | 读写绑定 |
icon | Icon | 读写绑定 |
iconTextGap | int | 读写绑定 |
itemListeners | ItemListener[] | 只读 |
layout | LayoutManager | 只写 |
margin | Insets | 读写绑定 |
mnemonic | char | 读写绑定 |
mnemonic | int | 只写 |
model | ButtonModel | 读写绑定 |
multiClickThreshhold | long | 读写 |
pressedIcon | Icon | 读写绑定 |
rolloverEnabled | boolean | 读写绑定 |
rolloverIcon | Icon | 读写绑定 |
rolloverSelectedIcon | Icon | 读写绑定 |
selected | boolean | 读写 |
selectedIcon | Icon | 读写绑定 |
selectedObjects | Object[] | 只读 |
text | String | 读写绑定 |
UI | ButtonUI | 读写 |
verticalAlignment | int | 读写绑定 |
verticalTextPosition | int | 读写绑定 |
在这里值得一提的就是multiClickThreshhold。这个属性表示以毫秒计数的时间。如果一个按钮在这段时间间隔被鼠标多次选中,并不会产生额外的动作事件。默认情况下这个属性值为0,意味着每一次点击都会产生一个事件。为了避免在重要的对话框中偶然重复提交动作的发生,应将这个属性值设置0以上的合理值。
ButtonModel/Class DefaultButtonModel接口
ButtonModel接口被用来描述AbstractButton组件的当前状态。另外,他描述了为所有不同的AbstractButton子类所支持的事件监听器对象的集合。其定义如下:
public interface ButtonModel extends ItemSelectable { // Properties public String getActionCommand(); public void setActionCommand(String newValue); public boolean isArmed(); public void setArmed(boolean newValue); public boolean isEnabled(); public void setEnabled(boolean newValue); public void setGroup(ButtonGroup newValue); public int getMnemonic(); public void setMnemonic(int newValue); public boolean isPressed(); public void setPressed(boolean newValue); public boolean isRollover(); public void setRollover(boolean newValue); public boolean isSelected(); public void setSelected(boolean newValue); // Listeners public void addActionListener(ActionListener listener); public void removeActionListener(ActionListener listener); public void addChangeListener(ChangeListener listener); public void removeChangeListener(ChangeListener listener); public void addItemListener(ItemListener listener); public void removeItemListener(ItemListener listener); }
我们将要使用的特定的ButtonModel实现是DefaultButtonModel类,除非我们定义了自己的类。DefaultButtonModel类定义了不同的事件监听器的所有事件注册方法并且管理按钮状态并组织在ButtonGroup中。表4-12显示其9个属性。除了selectedObjects以外,他们均来自ButtonGroup接口,selectedObjects属性是DefaultButtonModel类的新成员,但是对于JToggleButton十分有用。在第5章中将会讨论ToggleButtonModel。
DefaultButtonModel属性
属性名 |
数据类型 |
访问性 |
actionCommand |
String |
读写 |
armed |
boolean |
读写 |
enabled |
boolean |
读写 |
group |
ButtonGroup |
读写 |
mnemonic |
int |
读写 |
pressed |
boolean |
读写 |
rollover |
boolean |
读写 |
selected |
boolean |
读写 |
selectedObjects |
Object[] |
只读 |
大多数情况下,我们并不直接访问ButtonModel。相反,使用ButtonModel的组件封装他们属性调用来更新模型属性。
理解AbstractButton热键
热键是一种特殊的键盘快捷键,当按下时会使用一个特定的动作发生。在前的JLable类一节中讨论JLablel时,按下所显示的热键会使得相关联的组件获得输入焦点。在AbstractButton的情况下,按下按键的热键会使得按钮被选中。
热键的实际点击需要一个观感特定的热键的点击(这个键通常是Alt键)。所以,如果一个按钮的热键是B键,我们需要按下Alt-B来激活具有B热键的按钮。当按钮被激活时,所注册的监听器会被通知相应的状态变化。例如,对于JButton,所有的ActionListener对象都会被通知。
如果热键是按钮文本标签的一部分,我们会看到这个字符以下划线表示。这会由于当前的观感不同而有不同的显示。另外,如果热键并不是文本标签的一部分,对于特定的热键的选中并不有可见的指示符,除非观感在工具提示文本中进行显示。
图4-11显示了两个按钮:一个具有W热键,而另一个具有H热键。左边的按钮在其内容具有W的标签,所以第一个W会以下划线显示。第二个组件并没有由按钮上的这种行为获益,但是在Ocean观感中,如果工具提示文本进行了设置则会时行标识。
要为抽象按钮赋予一个热键,我们可以使用任意一个setMnemonic()方法。其中一个接受char参数,而另一个则接受int参数。就个人而言,我比较喜欢int版本,其参数值是KeyEvent类中众多VK_*常量的一个。我们也可以通过displayedMnemonicIndex属性来指定热键。
AbstractButton button1 = new JButton("Warning"); button1.setMnemonic(KeyEvent.VK_W); content.add(button1);
理解AbstractButton图标
AbstractButton具有七个特定的图标属性。默认的图标是icon属性。这个属性用于所有的情况,除非指定了一个不同的图标或是组件提供了默认的行为。selectedIcon属性是按钮被选中时所使用的图标。pressedIcon是按钮被按下时所用的图标。使用这两种图标中的哪一种依赖于组件,因为JButton被按下但是并没有被选中,而JCheckBox被选中却没有被按下。
当按钮通过setEnabled(false)被禁止时要使用disabledIcon与disabledSelectedIcon属性。默认情况下,如果图标是一个ImageIcon,将会使用图标的一个灰度平衡版本。
其他的两个属性,rolloverIcon与rolloverSelectedIcon允许我们当鼠标划过按钮时(rolloverEnabled为true)显示不同的图标。
理解内部的AbstractButton位置
horizontalAlignment, horizontalTextPosition, verticalAlignment与verticalTextPostion属性与JLabel类共享相同的设置与行为。表4-13列出这些属性。
位置属性 |
可用调用 |
horizontalAlignment |
LEFT, CENTER, RIGHT |
horizontalTextPosition |
LEFT, CENTER, RIGHT |
verticalAlignment |
TOP, CENTER, BOTTOM |
verticalTextPosition |
TOP, CENTER, BOTTOM |
尽管我们并不会直接创建一个AbstractButton实例,但是我们会创建其子类。所有子类共享一个共同的事件处理功能集合。我们可以向抽象按钮注册PropertyChangeListener,ActionListener,ItemListener以及ChangeListener对象。在这里将会讨论PropertyChangeListener对象,其余的对象将会在后续的章节中进行讨论。
与JComponent类类似,AbstractButton组件支持当类的实例的绑定属性变化时支持PropertyChangeListener对象注册的检测。与JComponent类不同的是,AbstractButton组件提供了下列的类常量集合来表示不同的属性变化:
•BORDER_PAINTED_CHANGED_PROPERTY •CONTENT_AREA_FILLED_CHANGED_PROPERTY •DISABLED_ICON_CHANGED_PROPERTY •DISABLED_SELECTED_ICON_CHANGED_PROPERTY •FOCUS_PAINTED_CHANGED_PROPERTY •HORIZONTAL_ALIGNMENT_CHANGED_PROPERTY •HORIZONTAL_TEXT_POSITION_CHANGED_PROPERTY •ICON_CHANGED_PROPERTY •MARGIN_CHANGED_PROPERTY •MNEMONIC_CHANGED_PROPERTY •MODEL_CHANGED_PROPERTY •PRESSED_ICON_CHANGED_PROPERTY •ROLLOVER_ENABLED_CHANGED_PROPERTY •ROLLOVER_ICON_CHANGED_PROPERTY •ROLLOVER_SELECTED_ICON_CHANGED_PROPERTY •SELECTED_ICON_CHANGED_PROPERTY •TEXT_CHANGED_PROPERTY •VERTICAL_ALIGNMENT_CHANGED_PROPERTY •VERTICAL_TEXT_POSITION_CHANGED_PROPERTY
所以,我们可以创建一个使用这些常量的PropertyChangeListener,而不需要硬编码特定的文本字符串,如列表4-5所示。
import javax.swing.*;
import java.beans.*;
public class AbstractButtonPropertyChangeListener
implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if (e.getPropertyName().equals(AbstractButton.TEXT_CHANGED_PROPERTY)) {
String newText = (String) e.getNewValue();
String oldText = (String) e.getOldValue();
System.out.println(oldText + " changed to" + newText);
} else if (e.getPropertyName().equals(AbstractButton.ICON_CHANGED_PROPERTY)) {
Icon icon = (Icon) e.getNewValue();
if (icon instanceof ImageIcon) {
System.out.println("New icon is an image");
}
}
}
}