Java + Jgoodies绑定:单选按钮绑定

时间:2010-04-14 15:27:11

标签: java radio-button jgoodies

我很难过......我正在尝试使用JGoodies绑定将radiobutton绑定到Enum属性。我似乎无法让它发挥作用。下面是一个简单的例子,它是一个bean表,每个bean都有一个不可变的数字和一个可变的“形容词”属性。无线电按钮被绑定到“形容词”属性。单击单选按钮确实会更改形容词,并且在表格中选择新项目会更新单选按钮,但按下单选按钮不会清除其他单选按钮。为什么会这样,我该如何解决?

我是否需要使用PropertyChangeSupport? (它似乎没有任何区别)

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

1 个答案:

答案 0 :(得分:2)

DOH!我想到了。我错过了两件事:

  1. 属性更改支持是必要的,我忘了将这些行添加到具有属性更改支持的bean中:

    public void addPropertyChangeListener(PropertyChangeListener pcl)
    {
        this.pcs.addPropertyChangeListener(pcl);
    }
    public void removePropertyChangeListener(PropertyChangeListener pcl)
    {
        this.pcs.removePropertyChangeListener(pcl);
    }
    
  2. BeanAdapter构造函数接受第二个参数以确保它从相关bean获取更改事件:

    final BeanAdapter<NumberBean> pNumber = 
      new BeanAdapter<NumberBean>((NumberBean)null, true);