好的,这是一个小技巧。有很多问题很难解决。
ButtonGroup 是一个具体的类,因此制作自定义版本很困难(这就是我喜欢interfaces 的原因),它更加复杂,因为它非常依赖private(或包私有)属性,没有提供任何合理的扩展点
因此,这留下了两种行动方案,要么使用反射,要么复制基类并进行我们自己的修改——这两种情况都不愉快。
所以,在我复制的所有代码中,我只修改了一个方法...
public void setSelected(ButtonModel m, boolean b) {
if (b) {
if (m != selection) {
ButtonModel oldSelection = selection;
selection = m;
if (oldSelection != null && oldSelection != m) {
oldSelection.setSelected(false);
}
m.setSelected(true);
}
} else if (selection != null) {
ButtonModel oldSelection = selection;
selection = null;
oldSelection.setSelected(false);
}
}
基本上,现在支持取消选择当前元素
public class UnselectableButtonGroup extends ButtonGroup {
// the list of buttons participating in this group
protected Vector<AbstractButton> buttons = new Vector<AbstractButton>();
/**
* The current selection.
*/
ButtonModel selection = null;
/**
* Creates a new <code>ButtonGroup</code>.
*/
public UnselectableButtonGroup() {
}
/**
* Adds the button to the group.
*
* @param b the button to be added
*/
public void add(AbstractButton b) {
if (b == null) {
return;
}
buttons.addElement(b);
if (b.isSelected()) {
if (selection == null) {
selection = b.getModel();
} else {
b.setSelected(false);
}
}
b.getModel().setGroup(this);
}
/**
* Removes the button from the group.
*
* @param b the button to be removed
*/
public void remove(AbstractButton b) {
if (b == null) {
return;
}
buttons.removeElement(b);
if (b.getModel() == selection) {
selection = null;
}
b.getModel().setGroup(null);
}
/**
* Clears the selection such that none of the buttons in the
* <code>ButtonGroup</code> are selected.
*
* @since 1.6
*/
public void clearSelection() {
if (selection != null) {
ButtonModel oldSelection = selection;
selection = null;
oldSelection.setSelected(false);
}
}
/**
* Returns all the buttons that are participating in this group.
*
* @return an <code>Enumeration</code> of the buttons in this group
*/
public Enumeration<AbstractButton> getElements() {
return buttons.elements();
}
/**
* Returns the model of the selected button.
*
* @return the selected button model
*/
public ButtonModel getSelection() {
return selection;
}
/**
* Sets the selected value for the <code>ButtonModel</code>. Only one
* button in the group may be selected at a time.
*
* @param m the <code>ButtonModel</code>
* @param b <code>true</code> if this button is to be selected,
* otherwise <code>false</code>
*/
public void setSelected(ButtonModel m, boolean b) {
if (b) {
if (m != selection) {
ButtonModel oldSelection = selection;
selection = m;
if (oldSelection != null && oldSelection != m) {
oldSelection.setSelected(false);
}
m.setSelected(true);
}
} else if (selection != null) {
ButtonModel oldSelection = selection;
selection = null;
oldSelection.setSelected(false);
}
}
/**
* Returns whether a <code>ButtonModel</code> is selected.
*
* @return <code>true</code> if the button is selected, otherwise
* returns <code>false</code>
*/
public boolean isSelected(ButtonModel m) {
return (m == selection);
}
/**
* Returns the number of buttons in the group.
*
* @return the button count
* @since 1.3
*/
public int getButtonCount() {
if (buttons == null) {
return 0;
} else {
return buttons.size();
}
}
}
我还研究了在按钮上使用ItemListener 和ChangeListener(以及两者)来尝试控制ButtonModel 的状态
我也尝试了Select Button Group,但它对我不起作用(我没有花任何时间尝试调试它,但它可能仍然对其他人有用)
可运行示例...
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
UnselectableButtonGroup bg = new UnselectableButtonGroup();
JRadioButton buttons[] = new JRadioButton[5];
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
for (int index = 0; index < buttons.length; index++) {
buttons[index] = new JRadioButton("Button " + index);
add(buttons[index], gbc);
bg.add(buttons[index]);
}
}
}
public class UnselectableButtonGroup extends ButtonGroup {
// the list of buttons participating in this group
protected Vector<AbstractButton> buttons = new Vector<AbstractButton>();
/**
* The current selection.
*/
ButtonModel selection = null;
/**
* Creates a new <code>ButtonGroup</code>.
*/
public UnselectableButtonGroup() {
}
/**
* Adds the button to the group.
*
* @param b the button to be added
*/
public void add(AbstractButton b) {
if (b == null) {
return;
}
buttons.addElement(b);
if (b.isSelected()) {
if (selection == null) {
selection = b.getModel();
} else {
b.setSelected(false);
}
}
b.getModel().setGroup(this);
}
/**
* Removes the button from the group.
*
* @param b the button to be removed
*/
public void remove(AbstractButton b) {
if (b == null) {
return;
}
buttons.removeElement(b);
if (b.getModel() == selection) {
selection = null;
}
b.getModel().setGroup(null);
}
/**
* Clears the selection such that none of the buttons in the
* <code>ButtonGroup</code> are selected.
*
* @since 1.6
*/
public void clearSelection() {
if (selection != null) {
ButtonModel oldSelection = selection;
selection = null;
oldSelection.setSelected(false);
}
}
/**
* Returns all the buttons that are participating in this group.
*
* @return an <code>Enumeration</code> of the buttons in this group
*/
public Enumeration<AbstractButton> getElements() {
return buttons.elements();
}
/**
* Returns the model of the selected button.
*
* @return the selected button model
*/
public ButtonModel getSelection() {
return selection;
}
/**
* Sets the selected value for the <code>ButtonModel</code>. Only one
* button in the group may be selected at a time.
*
* @param m the <code>ButtonModel</code>
* @param b <code>true</code> if this button is to be selected,
* otherwise <code>false</code>
*/
public void setSelected(ButtonModel m, boolean b) {
if (b) {
if (m != selection) {
ButtonModel oldSelection = selection;
selection = m;
if (oldSelection != null && oldSelection != m) {
oldSelection.setSelected(false);
}
m.setSelected(true);
}
} else if (selection != null) {
ButtonModel oldSelection = selection;
selection = null;
oldSelection.setSelected(false);
}
}
/**
* Returns whether a <code>ButtonModel</code> is selected.
*
* @return <code>true</code> if the button is selected, otherwise
* returns <code>false</code>
*/
public boolean isSelected(ButtonModel m) {
return (m == selection);
}
/**
* Returns the number of buttons in the group.
*
* @return the button count
* @since 1.3
*/
public int getButtonCount() {
if (buttons == null) {
return 0;
} else {
return buttons.size();
}
}
}
}