Toggle Buttons(一)
现在我们已经了解了相对简单的Swing组件JLabel与JButton的功能,现在我们来了解一些更为活跃的组件,特别是这些可以切换的组件。这些称之为可切换的组件-JToggleButton,JCheckBox与JRadioButton-为我们的用户提供了由一个选项集合中进行选择的方法。这些选项或者是打开,或者是关闭的,或者是允许,或者是禁止的。当表示在一个ButtonGroup中时,每次组中只有一个选项可以被选中。为了处理选中状态,组件与ToogleButtonModel共享一个共同的数据模型。下面我们来了解一下数据模型,使用ButtonGroup的组件组合机制,以及单个的组件。
5.1 ToggleButtonModel类
JToggleButton.ToggleButtonMode类是JToggleButton的一个公开内联类。这个类自定义了DefaultButtonModel类的行为,实现了ButtonModel接口。
自定义行为影响了ButtonGroup组件中所有AbstractButto的数据模型,ButtonGroup会在稍后的进行探讨。简单来说,一个ButtonGroup是AbstractButton组件的逻辑组合。在任意时刻,ButtonGroup中只有一个AbstractButton组件的selected属性被设置true,其他的必须为false。这并不意味着在组合中任意时刻只存在一个被选中的组件。如果ButtonGroup中的多个组件共享一个ButtonModel,那么在组合中就可以存在多个被选中的组件。如果没有组件共享模型,那么在组合中用户至多可以选中一个组件。一旦用户已经选择了一个组件,用户并不能交互的取消选择。然而,通过编程我们可以取消选中所有的组合元素。
JToggleButton.ToggleButtonModel定义如下:
public class ToggleButtonModel extends DefaultButtonModel { // Constructors public ToggleButtonModel(); // Properties public boolean isSelected(); public void setPressed(boolean newValue); public void setSelected(boolean newvalue); }
ToggleButtonModel类为JToogleButton以及其后面章节中所描述的子类JCheckBox与JRadioButton,以及将在第6章进行描述的JCheckBoxMenuItem与JRadioButtonMenuItem类定义了默认的数据模型。
5.2 ButtonGroup类
在描述ButtonGroup类之前,我们先来演示其用法。列表5-1中的程序创建了使用ToggleButtonModel的对象并将其放在一个组合中。正如程序所演示的,除了向屏幕容器添加组件之外,我们必须将每一个组件添加到相同的ButtonGroup中。这导致了对于每一个组件的一对add()方法调用。而且,按钮组合的容器会将组件放在一列中,并且使用一个带有标题的边框为用户标识组合,尽管这些并不是必须的。图5-1显示了程序的输出。
package swingstudy.ch04; import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.GridLayout; import javax.swing.AbstractButton; import javax.swing.BorderFactory; import javax.swing.ButtonGroup; import javax.swing.JCheckBox; import javax.swing.JCheckBoxMenuItem; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JRadioButton; import javax.swing.JRadioButtonMenuItem; import javax.swing.JToggleButton; import javax.swing.border.Border; public class AButtonGroup { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Runnable runner = new Runnable() { public void run() { JFrame frame = new JFrame("Button Group"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel = new JPanel(new GridLayout(0,1)); Border border = BorderFactory.createTitledBorder("Examples"); panel.setBorder(border); ButtonGroup group = new ButtonGroup(); AbstractButton abstract1 = new JToggleButton("Toggle Button"); panel.add(abstract1); group.add(abstract1); AbstractButton abstract2 = new JRadioButton("Radio Button"); panel.add(abstract2); group.add(abstract2); AbstractButton abstract3 = new JCheckBox("Check Box"); panel.add(abstract3); group.add(abstract3); AbstractButton abstract4 = new JRadioButtonMenuItem("Radio Button Menu Item"); panel.add(abstract4); group.add(abstract4); AbstractButton abstract5 = new JCheckBoxMenuItem("Check Box Menu Item"); panel.add(abstract5); group.add(abstract5); frame.add(panel, BorderLayout.CENTER); frame.setSize(300, 200); frame.setVisible(true); } }; EventQueue.invokeLater(runner); } }
正如前面所说的,ButtonGroup类表示AbstractButton组件的逻辑组合。ButtonGroup并不是一个可视化组件;所以,当使用ButtonGroup时在屏幕上并没有任何可见的内容。任何的AbstractButton组件可以通过public void add(AbstractButton abstractButton)方法添加到组合中。尽管任意的AbstractButton组件都可以属于一个ButtonGroup,只有当组件的数据模型是ToggleButtonModel时组合才会起作用。在ButtonGroup中具有一个模型为ToggleButtonModel的组件的结果是在组件被选中之后,ButtonGroup会出取消选中组合中当前被选中的组件。
尽管add()方法通常是我们唯一需要的方法,下面的类定义显示了其并不是ButtonGroup中唯一的方法:
public class ButtonGroup implements Serializable { // Constructor public ButtonGroup(); // Properties public int getButtonCount(); public Enumeration getElements(); public ButtonModel getSelection(); // Other methods public void add(AbstractButton aButton); public boolean isSelected(ButtonModel theModel) ; public void remove(AbstractButton aButton); public void setSelected(ButtonModel theModel, boolean newValue); }
如上的类定义所显示的一件有趣的事就是给定一个ButtonGroup,我们并不能直接确定被选中的AbstractButton。我们只可以直接查询哪一个ButtonModel被选中。然而,getElements()可以返回组合中所有AbstractButton元素的Enumeration。然后我们可以使用类似如下的代码在所有的按钮中进行遍历来确定被选中的按钮:
Enumeration elements = group.getElements(); while (elements.hasMoreElements()) { AbstractButton button = (AbstractButton)elements.nextElement(); if (button.isSelected()) { System.out.println("The winner is: " + button.getText()); break; // Don't break if sharing models -- could show multiple buttons selected } }
ButtonGroup另一个有趣的方法就是setSelected()。这个方法的两个参数是ButtonModel与boolean。如果boolean的值为false,则选中的请求会被忽略。如果ButtonModel并不是ButtonGroup中的按钮的模型,那么ButtonGroup会取消选中当前被选中的模型,从而使得组合中没有按钮被选中。这个方法的正确使用是使用组合中组件的模型以及一个true的新状态进行方法调用。例如,如果aButton是一个AbstractButton而aGroup是ButtonGroup,那么方法的调用类似于aGroup.setSelected(aButton.getModel(), true)。
下面我们来了解一下数据模型为ToggleButtonModel的各种组件。