Question:
I have several checkboxes and I want one checkbox to
cause all of the checkboxes to be selected when it is selected. How
can I do this?
Answer:
Even though the combined AWT and Swing packages provide an enormous
breadth of functionality, they do not cover every scenario you will
run into. The ButtonGroup class is designed to implement radio
buttons, a group of buttons whose selected states are mutually
exclusive. Therefore it is not suitable for your task. Implementing
the functionality on your own, however, is rather easy.
A "select all" button should cause all the buttons it is associated with
to be selected when it is selected. It should also become deselected
when any of the other buttons are deselected while it is selected.
I have provided a code example implementing a SelectAllGroup class
that will do this for you. The class itself implements the
ActionListener interface. That is so it can register itself as an
ActionListener with all of the buttons in order to detect selection
and deselection events. It uses a Vector to store all of the buttons
in the group except for the select all button. When a button is added
to the group, it is stored in the Vector and the SelectAllGroup object
adds itself as an ActionListener of the button. When a button is
removed from the group, it is removed from the Vector and the
SelectAllGroup object removes itself as an ActionListener of the
button. The select all button is referenced by a separate
_selectAllButton member variable that is set with
setSelectAllButton(). The SelectAllGroup object also adds itself as
an ActionListener of this button.
All the grunt work is done in actionPerformed(), which implements a
simple state machine with explicit Java code. If the ActionEvent
originates from the "select all" button and the button is selected, then the
method iterates through all of the buttons, invoking doClick() if they
are not already selected. I use doClick() instead of setSelected()
because setSelected() will not cause any of the buttons'
ActionListeners to be notified. If the ActionEvent comes from one of
the buttons in the group, then the "select all" button is deselected
only if it is currently selected and the button in the group is being
deselected.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
public class SelectAll extends JFrame {
public static class SelectAllGroup implements ActionListener {
AbstractButton _selectAllButton;
Vector _buttons;
public SelectAllGroup() {
_selectAllButton = null;
_buttons = new Vector();
}
public void setSelectAllButton(AbstractButton b) {
if(_selectAllButton != null)
_selectAllButton.removeActionListener(this);
_selectAllButton = b;
_selectAllButton.addActionListener(this);
}
public boolean addButton(AbstractButton b) {
if(_buttons.add(b)) {
b.addActionListener(this);
return true;
}
return false;
}
public boolean removeButton(AbstractButton b) {
if(_buttons.remove(b)) {
b.removeActionListener(this);
return true;
}
return false;
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
AbstractButton button;
if(_selectAllButton != null &&
_selectAllButton.equals(source) &&
_selectAllButton.isSelected())
{
Iterator it = _buttons.iterator();
while(it.hasNext()) {
button = (AbstractButton)it.next();
// Using setSelected will not trigger an actionEvent,
// so we use doClick() instead.
if(!button.isSelected()) {
// We want all the other ActionListeners
// to be called, but not ourselves.
button.removeActionListener(this);
button.doClick();
button.addActionListener(this);
}
}
} else if(_buttons.contains(source)) {
button = (AbstractButton)source;
if(!button.isSelected() && _selectAllButton.isSelected()) {
_selectAllButton.removeActionListener(this);
_selectAllButton.doClick();
_selectAllButton.addActionListener(this);
}
}
}
}
SelectAllGroup _buttonGroup;
public SelectAll() {
Container contentPane = getContentPane();
JCheckBox checkBox;
contentPane.setLayout(new FlowLayout());
_buttonGroup = new SelectAllGroup();
checkBox = new JCheckBox("Select All");
_buttonGroup.setSelectAllButton(checkBox);
contentPane.add(checkBox);
for(int i = 1; i <= 5; i++) {
checkBox = new JCheckBox(Integer.toString(i));
_buttonGroup.addButton(checkBox);
contentPane.add(checkBox);
}
}
public static final void main(String[] args) {
SelectAll frame;
frame = new SelectAll();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
Window window = e.getWindow();
window.setVisible(false);
window.dispose();
System.exit(0);
}
});
frame.pack();
frame.setTitle("Select All Button Demo");
frame.setVisible(true);
}
}