title: Java + Jgoodies binding: radio button binding
body: <p>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? </p>
  
  <p>And do I need to use PropertyChangeSupport? (it doesn't seem to make any difference)</p>
  
  <pre><code>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 &lt;T&gt; T pick(T[] values, int i)
      {
          int j = i % values.length;
          if (j &lt; 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&lt;NumberBean&gt; pNumber = 
          new BeanAdapter&lt;NumberBean&gt;((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 &lt; 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 subpanel = 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);
      }
  }
  </code></pre>