Java + Jgoodies binding: radio button binding
I'm stumped... I'm trying to use JGoodies binding to bind a radiobutton to an Enum property. I can't seem to get it to work. Below is a simple example, it's a table of beans each with an immutable number and a mutable "adjective" property. The radiobuttons are bound to the "adjective" property. Clicking on the radio buttons does change the adjective, and selecting a new item in the table does update the radio buttons, but pressing a radio button does not clear the other radio buttons. Why is this, and how do I fix it?
And do I need to use PropertyChangeSupport? (it doesn't seem to make any difference)
package com.example.jgoodies;
import java.beans.PropertyChangeSupport;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
import com.jgoodies.binding.adapter.Bindings;
import com.jgoodies.binding.beans.BeanAdapter;
import com.jgoodies.binding.value.ValueModel;
public class RadioButtonBindingExample extends JFrame {
static public <T> T pick(T[] values, int i)
{
int j = i % values.length;
if (j < 0)
j += values.length;
return values[j];
}
enum Adjective { SHORT, TALL, RED, GREEN;
@Override public String toString() { return name().toLowerCase(); }
}
static public class NumberBean
{
final private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
final private int n;
private Adjective adjective;
public NumberBean(int n) {
this.n = n;
this.adjective = pick(Adjective.values(), n);
}
public int getNumber() { return this.n; }
public Adjective getAdjective() { return this.adjective; }
public void setAdjective(Adjective a) {
Adjective old = this.adjective;
this.adjective = a;
this.pcs.firePropertyChange("adjective", old, a);
}
public String getLabel() { return this.adjective + " " + n; }
}
final BeanAdapter<NumberBean> pNumber =
new BeanAdapter<NumberBean>((NumberBean)null);
final private NumberBeanTableModel numberBeanDataModel = new NumberBeanTableModel(100);
final private JPanel numberBeanDisplayPanel = new JPanel();
public static class NumberBeanTableModel extends AbstractTableModel {
final private NumberBean[] v;
public NumberBeanTableModel(int nrows)
{
this.v = new NumberBean[nrows];
for (int i = 0; i < nrows; ++i)
{
this.v[i] = new NumberBean(i);
}
}
public int getColumnCount() { return 2; }
public int getRowCount() { return this.v.length;}
public NumberBean getNumberBean(int row)
{
return this.v[row];
}
public Object getValueAt(int row, int col) {
NumberBean nb = this.v[row];
return (col==0 ? nb.getNumber() : nb.getAdjective());
}
};
NumberBeanTableModel getNumberBeanModel() { return this.numberBeanDataModel; }
public RadioButtonBindingExample(String title)
{
super(title);
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
JTable table = new JTable(getNumberBeanModel());
table.getColumnModel().getColumn(0).setHeaderValue("row number");
final ListSelectionModel lsm = table.getSelectionModel();
lsm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
lsm.addListSelectionListener(new ListSelectionListener() {
@Override public void valueChanged(ListSelectionEvent event) {
int i = lsm.getLeadSelectionIndex();
NumberBean nb = getNumberBeanModel().getNumberBean(i);
onTableSelection(nb);
}});
JScrollPane scrollpane = new JScrollPane(table);
JLabel rowLabel = new JLabel();
Bindings.bind(rowLabel,
this.pNumber.getValueModel("label"));
JPanel subpan开发者_JAVA技巧el = this.numberBeanDisplayPanel;
subpanel.setLayout(new BoxLayout(subpanel, BoxLayout.PAGE_AXIS));
subpanel.add(rowLabel);
ValueModel rmodel = this.pNumber.getValueModel("adjective");
for (Adjective adjective : Adjective.values())
{
JRadioButton r = new JRadioButton(adjective.toString());
Bindings.bind(r, rmodel, adjective);
subpanel.add(r);
}
subpanel.setVisible(false);
panel.add(subpanel);
panel.add(scrollpane);
getContentPane().add(panel);
}
protected void onTableSelection(NumberBean nb) {
this.pNumber.setBean(nb);
this.numberBeanDisplayPanel.setVisible(true);
}
public static void main(String[] args)
{
RadioButtonBindingExample rbbe =
new RadioButtonBindingExample("radio button binding example");
rbbe.pack();
rbbe.setVisible(true);
rbbe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
DOH! I figured it out. I was missing two things:
Property change support is necessary, I forgot to add these lines to the bean with property change support:
public void addPropertyChangeListener(PropertyChangeListener pcl) { this.pcs.addPropertyChangeListener(pcl); } public void removePropertyChangeListener(PropertyChangeListener pcl) { this.pcs.removePropertyChangeListener(pcl); }
The BeanAdapter constructor takes a second argument to ensure it is getting change events from the bean in question:
final BeanAdapter<NumberBean> pNumber = new BeanAdapter<NumberBean>((NumberBean)null, true);
精彩评论