如何以编程方式更新jtable单元格和TableModel?

时间:2013-11-09 09:30:34

标签: java swing jtable

我需要确保选中列中只有一个复选框。因此,当用户选择复选框时,我必须取消选择之前选择的。

我尝试在TableModel的setValueAt方法中执行此操作,但我无法更新单元格,即使是按钮单击的单元格也是如此。我没有显示我的所有代码,而是创建了有助于尝试解决方案的简单示例:

public class DateFormatDemo extends JFrame
{
    private JTable dataSearchResultTable;

    public DateFormatDemo()
    {
        JPanel panel = new JPanel(new GridLayout(2, 1, 5, 10));
        panel.setPreferredSize(new Dimension(500, 300));
        dataSearchResultTable = new JTable(new MyTableModel());

        dataSearchResultTable.setSelectionBackground(new Color(0xaaaaff));
        dataSearchResultTable.setFillsViewportHeight(true);
        dataSearchResultTable.setRowSelectionAllowed(true);
        dataSearchResultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        dataSearchResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
        dataSearchResultTable.setRowHeight(25);

        panel.add(new JScrollPane(dataSearchResultTable));
        super.getContentPane().add(panel);
        super.pack();
        super.setDefaultCloseOperation(EXIT_ON_CLOSE);
        super.setVisible(true);
    }

    class MyTableModel extends AbstractTableModel
    {
        private String[] columnNames = { "First Name", "Last name", "Vegetarian" };
        private Object[][] data;

        MyTableModel()
        {
            data = new Object[][] { { "Vova", "KipokKipokKipokKipok", false }, { "Olia", "Duo", true },
                    { "Ivan", "Brown", false } };
            fireTableDataChanged();
        }

        public int getColumnCount()
        {
            return columnNames.length;
        }

        public int getRowCount()
        {
            return data.length;
        }

        public String getColumnName(int col)
        {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col)
        {
            if (data.length > 0 && data[0] != null) {
                return data[row][col];
            }
            return null;
        }

        public Class getColumnClass(int c)
        {
            Object valueAt = getValueAt(0, c);
            return valueAt == null ? Object.class : valueAt.getClass();
        }

        public boolean isCellEditable(int row, int col)
        {
            return true;
        }

        public void setValueAt(Object value, int row, int col)
        {
            if (data.length > 0 && data[0] != null) {
                data[row][col] = value;
                fireTableCellUpdated(row, col);
            }
        }
    }

    public static void main(String[] args) throws ParseException
    {
        new DateFormatDemo();
    }
}

所以,我希望Vegeterian列只选中一个复选框,当用户选择一个复选框时,另一个复选框应该被取消选中。

谢谢!

1 个答案:

答案 0 :(得分:1)

很多内容将归结为您的模型的结构。

基本上,在setValueAt方法中,当您确定“复选框”列已更改时,您需要找到该列中的任何值(我推测)true并将其设置为false,触发TableCellUpdated事件,表示您已更改了单元格值。

假设只有一个单元格可以true,那么您可以在该点断开并继续按正常方式修改单元格值。

另一个风险更大的解决方案可能是维护最后一个单元格的行索引,并在值发生变化时简单地休息......

这里的风险来自于确保在构建模型时,您知道哪一行是true,基础数据是否遵循您的规则(并且只有一行true行)且缺乏控制权支持数据(可能不在此示例中,但在其他示例中)

return valueAt == null ? Object.class : valueAt.getClass();方法中使用getColumnClass是一个坏主意。你应该传回适当的已知值。

在构造函数中调用fireTableDataChanged是没有意义的,没有人可能已经为您的模型附加了一个监听器。