views:

254

answers:

2

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 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);
    }
}
A: 

DOH! I figured it out. I was missing two things:

  1. 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);
    }
    
  2. 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); 
    
Jason S
A: 

hi, I have the same problem but i'm using a Presentation model and BufferedModel. I have just tried to use your code but it doesn't seems to work for me.

I think I havn't pasted your code in the right place. Can you post the entire example?

Thanks

Please do not post an answer that is really a question or comment. Ask a new question instead.
Jason S