Java 如何在JTable中将JRadioButton添加到组中

Java 如何在JTable中将JRadioButton添加到组中,java,swing,jtable,jradiobutton,buttongroup,Java,Swing,Jtable,Jradiobutton,Buttongroup,我使用渲染器和编辑器将单选按钮添加到JTable。我还为同一个项目创建了一个组。我无法使用此原则实现排他性(只能选择一个单选按钮)。请参阅下面我的代码,并感谢您的回复 渲染器和编辑器类: class RadioButtonRenderer implements TableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean

我使用渲染器和编辑器将单选按钮添加到
JTable
。我还为同一个项目创建了一个组。我无法使用此原则实现排他性(只能选择一个单选按钮)。请参阅下面我的代码,并感谢您的回复

渲染器和编辑器类:

class RadioButtonRenderer implements TableCellRenderer {

    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        if (value == null)
            return null;
        return (Component) value;
    }
}

class RadioButtonEditor extends DefaultCellEditor implements ItemListener {
    private JRadioButton button;

    public RadioButtonEditor(JCheckBox checkBox) {
        super(checkBox);
    }

    public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {
        if (value == null)
            return null;
        button = (JRadioButton) value;
        button.addItemListener(this);
        return (Component) value;
    }

    public Object getCellEditorValue() {
        button.removeItemListener(this);
        return button;
    }

    public void itemStateChanged(ItemEvent e) {
        super.fireEditingStopped();
    }
}
这是准备数据和进行分组的地方:

private void displayPhoneListShow(Person person) {

    DefaultTableModel dm = new DefaultTableModel() {
        @Override
        public boolean isCellEditable(int row, int column) {
            return true;
        }
    };

    Object[] objects = new Object[3];
    Object[] tableColumnNamesPhone = new Object[3];

    tableColumnNamesPhone[0] = "Select";
    tableColumnNamesPhone[1] = "Phone Number";
    tableColumnNamesPhone[2] = "Preferred";

    dm.setColumnIdentifiers(tableColumnNamesPhone);
    ListIterator<Phone> phoneList = person.getPhoneList().listIterator();
    while (phoneList.hasNext()) {
        Phone phone = phoneList.next();
        objects[0] = new JRadioButton(("^"));
        objects[1] = phone.getPhoneNumber();
        objects[2] = phone.getPreferred();
        dm.addRow(objects);
    }
    this.phoneTable.setModel(dm);

    ButtonGroup group = new ButtonGroup();
    for (int row = 0; row < dm.getRowCount(); row++) {
        JRadioButton radio = (JRadioButton) dm.getValueAt(row, 0);
        group.add(radio);
    }

    phoneTable.getColumn("Select").setCellRenderer(
            new RadioButtonRenderer());
    phoneTable.getColumn("Select").setCellEditor(
            new RadioButtonEditor(new JCheckBox()));
}
private void displayPhoneListShow(个人){
DefaultTableModel dm=新的DefaultTableModel(){
@凌驾
公共布尔值可编辑(int行,int列){
返回true;
}
};
Object[]objects=新对象[3];
Object[]tableColumnNamesPhone=新对象[3];
tableColumnNamesPhone[0]=“选择”;
tableColumnNamesPhone[1]=“电话号码”;
tableColumnNamesPhone[2]=“首选”;
dm.setColumnIdentifiers(tableColumnNamesPhone);
ListIterator phoneList=person.getPhoneList().ListIterator();
while(phoneList.hasNext()){
Phone Phone=phoneList.next();
objects[0]=新的JRadioButton((“^”);
对象[1]=phone.getPhoneNumber();
对象[2]=phone.getPreferred();
dm.addRow(对象);
}
this.phoneTable.setModel(dm);
ButtonGroup=新建ButtonGroup();
对于(int row=0;row
我仍然无法达到这个结果。我还尝试将
ButtonGroup group=new ButtonGroup()
添加为类变量,也是
RadioButtonRenderer
类的一部分,并向该组添加了按钮。但结果却无动于衷


请建议。

另一种选择是,使用
JComboBox
作为一行中相互排斥的选项。为方便起见,提供了一个专门用于此的构造函数。该结果还可以更有效地利用行中的水平空间。下面是一个示例。另请参见这些其他

  • 来自@mKorbel的
    StatusRenderer
    StatusEditor
    ,Mac OS X的图:

  • 图为一个相关的Mac OS X:

  • 来自@mKorbel的
    StatusRenderer
    StatusEditor
    窗口的图:

  • 使用Windows中的
    DefaultTableCellRenderer
    DefaultCellEditor
    的图(请参见注释):

  • 代码:

    import java.awt.*;
    导入java.awt.event.*;
    导入java.text.DateFormat;
    导入java.text.simpleDataFormat;
    导入java.util.Date;
    导入java.util.Vector;
    导入javax.swing.AbstractAction;
    导入javax.swing.AbstractCellEditor;
    导入javax.swing.BorderFactory;
    导入javax.swing.ButtonGroup;
    导入javax.swing.JFrame;
    导入javax.swing.JPanel;
    导入javax.swing.JRadioButton;
    导入javax.swing.JScrollPane;
    导入javax.swing.JSpinner;
    导入javax.swing.JTable;
    导入javax.swing.JToolBar;
    导入javax.swing.SpinnerDateModel;
    导入javax.swing.SwingUtilities;
    导入javax.swing.table.AbstractTableModel;
    导入javax.swing.table.DefaultTableCellRenderer;
    导入javax.swing.table.TableCellEditor;
    导入javax.swing.table.TableCellRenderer;
    导入javax.swing.table.TableColumnModel;
    公共类JRADIOASrenderEditor扩展了JPanel{
    私有静态最终字符串[]列名称={
    “列表ID”、“到期日期”、“状态”、“创建日期”};
    私有静态最终日期格式日期\格式=新的SimpleDataFormat(“dd/MM/yyyy”);
    私有静态最终日期格式时间\格式\长=新的SimpleDataFormat(“HH:mm:ss,SSS”);
    私有MyTableModel tableModel;
    专用JTable表;
    私有JFrame=新JFrame(“TestRadioButtonRenderer”);
    公共jradioasrendereditor(){
    超级(新边界布局(0,5));
    setBorder(BorderFactory.createEmptyByOrder(5,5,5,5));
    tableModel=新的MyTableModel();
    table=新的JTable(tableModel);
    table.setDefaultEditor(Date.class,new DateEditor());
    table.setDefaultRenderer(Date.class,new DateRenderer());
    table.setDefaultEditor(Status.class,newstatusEditor());
    table.setDefaultRenderer(Status.class,newstatusRenderer());
    //注释前面两行并取消注释标准编辑器的以下内容
    //table.setDefaultEditor(Status.class,新的DefaultCellEditor(
    //新的JComboBox(新状态[]{Status.Single,Status.已婚,Status.discovered});
    添加(新的JScrollPane(表),BorderLayout.CENTER);
    JToolBar toolBar=新的JToolBar();
    工具栏。可设置浮动(false);
    添加(新抽象操作(“添加新”){
    @凌驾
    已执行的公共无效操作(操作事件e){
    tableModel.add(newtableentry());
    packTable();
    }
    });
    添加(新抽象操作(“删除”){
    @凌驾
    已执行的公共无效操作(操作事件e){
    tableModel.remove(table.getSelectedRow());
    }
    });
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    添加(新的JScrollPane(表),BorderLayout.CENTER);
    frame.add(工具栏,BorderLayout.NORTH);
    frame.pack();
    SwingUtilities.invokeLater(新的Runnable(){
    @凌驾
    公开募捐{
    frame.setVisible(true);
    }
    });
    }
    私有void packTable(){
    TableColumnModel columnModel=table.getColumnModel();
    int columnCount=table.getColumnCount();
    int rowCount=table.getRowCount();
    int[]preferredHeights=new int[columnCount][rowCount];
    TableCell渲染器;
    组件组件;
    对于(int col=0;
    
    import java.awt.*;
    import java.awt.event.*;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Vector;
    import javax.swing.AbstractAction;
    import javax.swing.AbstractCellEditor;
    import javax.swing.BorderFactory;
    import javax.swing.ButtonGroup;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JRadioButton;
    import javax.swing.JScrollPane;
    import javax.swing.JSpinner;
    import javax.swing.JTable;
    import javax.swing.JToolBar;
    import javax.swing.SpinnerDateModel;
    import javax.swing.SwingUtilities;
    import javax.swing.table.AbstractTableModel;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.TableCellEditor;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.table.TableColumnModel;
    
    public class JRadioAsRendererEditor extends JPanel {
    
        private static final String[] COLUMN_NAMES = {
            "List ID", "Expiration Date", "Status", "Date Created"};
        private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy");
        private static final DateFormat TIME_FORMAT_LONG = new SimpleDateFormat("HH:mm:ss,SSS");
        private MyTableModel tableModel;
        private JTable table;
        private JFrame frame = new JFrame("TestRadioButtonRenderer");
    
        public JRadioAsRendererEditor() {
            super(new BorderLayout(0, 5));
            setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
            tableModel = new MyTableModel();
            table = new JTable(tableModel);
            table.setDefaultEditor(Date.class, new DateEditor());
            table.setDefaultRenderer(Date.class, new DateRenderer());
            table.setDefaultEditor(Status.class, new StatusEditor());
            table.setDefaultRenderer(Status.class, new StatusRenderer());
    // comment the two preceding lines and uncomment the following for a standard editor
    // table.setDefaultEditor(Status.class, new DefaultCellEditor(
    // new JComboBox(new Status[]{Status.Single, Status.Married, Status.Divorced})));
    
            add(new JScrollPane(table), BorderLayout.CENTER);
            JToolBar toolBar = new JToolBar();
            toolBar.setFloatable(false);
            toolBar.add(new AbstractAction("Add new") {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    tableModel.add(new TableEntry());
                    packTable();
                }
            });
            toolBar.add(new AbstractAction("Remove") {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    tableModel.remove(table.getSelectedRow());
                }
            });
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(new JScrollPane(table), BorderLayout.CENTER);
            frame.add(toolBar, BorderLayout.NORTH);
            frame.pack();
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    frame.setVisible(true);
                }
            });
        }
    
        private void packTable() {
            TableColumnModel columnModel = table.getColumnModel();
            int columnCount = table.getColumnCount();
            int rowCount = table.getRowCount();
            int[][] preferredHeights = new int[columnCount][rowCount];
            TableCellRenderer renderer;
            Component comp;
            for (int col = 0; col < columnCount; col++) {
                renderer = columnModel.getColumn(col).getCellRenderer();
                if (renderer == null) {
                    renderer = table.getDefaultRenderer(tableModel.getColumnClass(col));
                }
                for (int row = 0; row < rowCount; row++) {
                    comp = renderer.getTableCellRendererComponent(table,
                        tableModel.getValueAt(row, col), false, false, row, col);
                    preferredHeights[col][row] = (int) comp.getPreferredSize().getHeight();
                }
            }
            for (int row = 0; row < rowCount; row++) {
                int pref = 0;
                for (int col = 0; col < columnCount; col++) {
                    pref = Math.max(pref, preferredHeights[col][row]);
                }
                table.setRowHeight(row, pref);
            }
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    JRadioAsRendererEditor tableTestPanel = new JRadioAsRendererEditor();
                }
            });
        }
    
        private enum Status {
    
            Single, Married, Divorced;
        }
    
        private class StatusPanel extends JPanel {
    
            private JRadioButton theSingleOption;
            private JRadioButton theMarriedOption;
            private JRadioButton theDivorcedOption;
            private ButtonGroup buttonGroup = new ButtonGroup();
    
            StatusPanel() {
                super(new GridLayout(0, 1));
                setOpaque(true);
                theSingleOption = createRadio(Status.Single);
                theMarriedOption = createRadio(Status.Married);
                theDivorcedOption = createRadio(Status.Divorced);
            }
    
            private JRadioButton createRadio(Status status) {
                JRadioButton jrb = new JRadioButton(status.toString());
                jrb.setOpaque(false);
                add(jrb);
                buttonGroup.add(jrb);
                return jrb;
            }
    
            public Status getStatus() {
                if (theMarriedOption.isSelected()) {
                    return Status.Married;
                } else if (theDivorcedOption.isSelected()) {
                    return Status.Divorced;
                } else {
                    return Status.Single;
                }
            }
    
            public void setStatus(Status status) {
                if (status == Status.Married) {
                    theMarriedOption.setSelected(true);
                } else if (status == Status.Divorced) {
                    theDivorcedOption.setSelected(true);
                } else {
                    theSingleOption.setSelected(true);
                }
            }
        }
    
        private class TableEntry {
    
            private int instanceNumber;
            private Long theId;
            private Date theExpirationDate;
            private Status theStatus;
            private Date theCreationDate;
    
            TableEntry() {
                instanceNumber++;
                theId = new Long(instanceNumber);
                theExpirationDate = new Date();
                theStatus = Status.Single;
                theCreationDate = new Date();
            }
    
            TableEntry(Long anId, Date anExpirationDate, Status aStatus, Date aCreationDate) {
                theId = anId;
                theExpirationDate = anExpirationDate;
                theStatus = aStatus;
                theCreationDate = aCreationDate;
            }
    
            public Long getId() {
                return theId;
            }
    
            public Date getExpirationDate() {
                return theExpirationDate;
            }
    
            public Status getStatus() {
                return theStatus;
            }
    
            public Date getCreationDate() {
                return theCreationDate;
            }
    
            public void setId(Long anId) {
                theId = anId;
            }
    
            public void setExpirationDate(Date anExpirationDate) {
                theExpirationDate = anExpirationDate;
            }
    
            public void setStatus(Status aStatus) {
                theStatus = aStatus;
            }
    
            public void setCreationDate(Date aCreationDate) {
                theCreationDate = aCreationDate;
            }
        }
    
        private class MyTableModel extends AbstractTableModel {
    
            private Vector<Object> theEntries;
    
            MyTableModel() {
                theEntries = new Vector<Object>();
            }
    
            @SuppressWarnings("unchecked")
            public void add(TableEntry anEntry) {
                int index = theEntries.size();
                theEntries.add(anEntry);
                fireTableRowsInserted(index, index);
            }
    
            public void remove(int aRowIndex) {
                if (aRowIndex < 0 || aRowIndex >= theEntries.size()) {
                    return;
                }
                theEntries.removeElementAt(aRowIndex);
                fireTableRowsDeleted(aRowIndex, aRowIndex);
    
            }
    
            public int getRowCount() {
                return theEntries.size();
            }
    
            @Override
            public String getColumnName(int column) {
                return COLUMN_NAMES[column];
            }
    
            @Override
            public Class<?> getColumnClass(int columnIndex) {
                switch (columnIndex) {
                    case 0:
                        return Long.class;
                    case 1:
                        return Date.class;
                    case 2:
                        return Status.class;
                    case 3:
                        return Date.class;
                }
                return Object.class;
            }
    
            @Override
            public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
                TableEntry entry = (TableEntry) theEntries.elementAt(rowIndex);
                switch (columnIndex) {
                    case 0:
                        try {
                            entry.setId(new Long(Long.parseLong(aValue.toString())));
                        } catch (NumberFormatException nfe) {
                            return;
                        }
                        break;
                    case 1:
                        entry.setExpirationDate((Date) aValue);
                        break;
                    case 2:
                        entry.setStatus((Status) aValue);
                        break;
                    case 3:
                        entry.setCreationDate((Date) aValue);
                        break;
                    default:
                        return;
                }
                fireTableCellUpdated(rowIndex, columnIndex);
            }
    
            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return true;
            }
    
            @Override
            public int getColumnCount() {
                return 4;
            }
    
            @Override
            public Object getValueAt(int rowIndex, int columnIndex) {
                TableEntry entry = (TableEntry) theEntries.elementAt(rowIndex);
                switch (columnIndex) {
                    case 0:
                        return entry.getId();
                    case 1:
                        return entry.getExpirationDate();
                    case 2:
                        return entry.getStatus();
                    case 3:
                        return entry.getCreationDate();
                }
                return null;
            }
        }
    
        private class DateRenderer extends DefaultTableCellRenderer {
    
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if (!(value instanceof Date)) {
                    return this;
                }
                setText(DATE_FORMAT.format((Date) value));
                return this;
            }
        }
    
        private class TimeRenderer extends DefaultTableCellRenderer {
    
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if (!(value instanceof Date)) {
                    return this;
                }
                setText(TIME_FORMAT_LONG.format((Date) value));
                return this;
            }
        }
    
        private class DateEditor extends AbstractCellEditor implements TableCellEditor {
    
            private JSpinner theSpinner;
    
            DateEditor() {
                theSpinner = new JSpinner(new SpinnerDateModel());
                theSpinner.setOpaque(true);
                theSpinner.setEditor(new JSpinner.DateEditor(theSpinner, "dd/MM/yyyy"));
            }
    
            @Override
            public Object getCellEditorValue() {
                return theSpinner.getValue();
            }
    
            @Override
            public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {
                theSpinner.setValue(value);
                if (isSelected) {
                    theSpinner.setBackground(table.getSelectionBackground());
                } else {
                    theSpinner.setBackground(table.getBackground());
                }
                return theSpinner;
            }
        }
    
        private class TimeEditor extends AbstractCellEditor implements TableCellEditor {
    
            private JSpinner theSpinner;
            private Object value;
    
            TimeEditor() {
                theSpinner = new JSpinner(new SpinnerDateModel());
                theSpinner.setOpaque(true);
                theSpinner.setEditor(new JSpinner.DateEditor(theSpinner, "HH:mm:ss,SSS"));
            }
    
            @Override
            public Object getCellEditorValue() {
                return theSpinner.getValue();
            }
    
            @Override
            public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {
                theSpinner.setValue(value);
                if (isSelected) {
                    theSpinner.setBackground(table.getSelectionBackground());
                } else {
                    theSpinner.setBackground(table.getBackground());
                }
                return theSpinner;
            }
        }
    
        private class StatusEditor extends AbstractCellEditor implements TableCellEditor {
    
            private StatusPanel theStatusPanel;
    
            StatusEditor() {
                theStatusPanel = new StatusPanel();
            }
    
            @Override
            public Object getCellEditorValue() {
                return theStatusPanel.getStatus();
            }
    
            @Override
            public Component getTableCellEditorComponent(JTable table, Object value,
                boolean isSelected, int row, int column) {
                theStatusPanel.setStatus((Status) value);
                if (isSelected) {
                    theStatusPanel.setBackground(table.getSelectionBackground());
                } else {
                    theStatusPanel.setBackground(table.getBackground());
                }
                return theStatusPanel;
            }
        }
    
        private class StatusRenderer extends StatusPanel implements TableCellRenderer {
    
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column) {
                setStatus((Status) value);
                if (isSelected) {
                    setBackground(table.getSelectionBackground());
                } else {
                    setBackground(table.getBackground());
                }
                return this;
            }
        }
    }