我尝试添加更多列时发生异常

时间:2013-08-22 15:39:39

标签: java swing jtable indexoutofboundsexception abstracttablemodel

我正在使用MVC设计模式制作一个GUI项目。这个程序包含JTable组件,为此我创建了一个扩展AbstractTableModel的类MyTableModel。正如您在MyModelClass中看到的,我有两个方法 addColumn& removeColumn ,它通常在表中添加/删除列,直到我已经到了这一点,当我必须将8个组合的3个初始列添加到我的构造函数中,然后尝试添加/删除列。 Here你可以看到程序截图。

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3
    at mvc.TTableModel.getValueAt(TTableModel.java:79)
    at mvc.TTableModel.getColumnClass(TTableModel.java:84)
    at javax.swing.JTable.getColumnClass(JTable.java:2697)
    at javax.swing.JTable.getCellRenderer(JTable.java:5682)
    at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2113)
    at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:2016)
    at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1812)
    at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
    at javax.swing.JComponent.paintComponent(JComponent.java:778)
    at javax.swing.JComponent.paint(JComponent.java:1054)
    at javax.swing.JComponent.paintChildren(JComponent.java:887)
    at javax.swing.JComponent.paint(JComponent.java:1063)
    at javax.swing.JViewport.paint(JViewport.java:731)
    at javax.swing.JComponent.paintChildren(JComponent.java:887)
    at javax.swing.JComponent.paint(JComponent.java:1063)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5221)
    at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1512)
    at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1443)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1236)
    at javax.swing.JComponent._paintImmediately(JComponent.java:5169)
    at javax.swing.JComponent.paintImmediately(JComponent.java:4980)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:796)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:784)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:784)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:757)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:706)
    at javax.swing.RepaintManager.access$1000(RepaintManager.java:62)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1651)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:727)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:688)
    at java.awt.EventQueue$3.run(EventQueue.java:686)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:697)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91).

代码段

public class TTableModel extends AbstractTableModel implements ThreeInputConstants{

    private ArrayList<Object> columnList;
    private List<boolean[]> data;

    public TTableModel() {
        this.columnList = new ArrayList<>();
        this.data = new ArrayList<>();

        // adds p, q, r
        columnList.add(THREE_INPUT_TITLES[0]);
        columnList.add(THREE_INPUT_TITLES[1]);
        columnList.add(THREE_INPUT_TITLES[2]);

        for (int i = 0; i < 8; i++) {
            boolean[] tempArray = new boolean[3];

            tempArray[0] = P_CONST[i];
            tempArray[1] = Q_CONST[i];
            tempArray[2] = R_CONST[i];

            data.add(i, tempArray);
        }

    }

    public void printListTemp() {
        System.out.println("Column list: " + columnList);
        System.out.println("Data: " + data);
    }

    public void addColumn(String header) {
        this.columnList.add(header);
        this.fireTableStructureChanged();
    }

    public void removeColumn(int columnIndex) {
        if (columnIndex >= 0 && columnIndex < getColumnCount()) {
            this.columnList.remove(columnIndex + INPUT_COLUMN_COUNT);
            this.fireTableStructureChanged();
        }
    }

    @Override
    public String getColumnName(int columnIndex) {
        return columnList.get(columnIndex).toString();
    }

    @Override
    public int getColumnCount() {
        return columnList.size();
    }

    @Override
    public int getRowCount() {
        return data.size();
    }

    @Override
    public void setValueAt(Object value, int row, int column) {
        //data[row][column] = value; 
        data.get(row)[column] = (boolean) value;
        this.fireTableCellUpdated(row, column);
    }

    @Override
    public Object getValueAt(int row, int column) {
        return data.get(row)[column];
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return getValueAt(0, columnIndex).getClass();
    }

}

public interface ThreeInputConstants {

    public static final Object THREE_INPUT_TITLES[] = {
            "p", "q", "r"
    };
    public static final boolean P_CONST[] = {
            true, true, true, true, 
            false, false, false, false
    };
    public static final boolean Q_CONST[] = {
            true, true, false, false, 
            true, true, false, false, 
    };
    public static final boolean R_CONST[] = {
            true, false, true, false, 
            true, false, true, false, 
    };
}

更新(已修复):

public void addColumn(String header) {
        this.columnList.add(header);

        for (int i = 0; i < data.size(); i++) {
            List<Boolean> rowList = data.get(i);
            while (rowList.size() < columnList.size()) {
                rowList.add(false);
            }
        }
        this.fireTableStructureChanged();
    }

2 个答案:

答案 0 :(得分:2)

您要向数据ArrayList添加8个条目,每个条目包含3个元素的数组。

for (int i = 0; i < 8; i++) {
    boolean[] tempArray = new boolean[3];

    tempArray[0] = P_CONST[i];
    tempArray[1] = Q_CONST[i];
    tempArray[2] = R_CONST[i];

    data.add(i, tempArray);
}

但错误信息:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 3 at 

表示您正在尝试检索索引为3的元素,即第4个元素。由于您的数组只有3个元素,因此会抛出ArrayIndexOutOfBoundsException异常。

检查调用getValueAt方法的客户端代码,并确保它不使用超过2的索引。

编辑:

尝试将getColumnCount和getRowCount更改为:

@Override
public int getColumnCount() {
    return data.size();        
}

@Override
public int getRowCount() {
    return columnList.size();
}

答案 1 :(得分:1)

我的猜测是,在您调用addColumn()后会发生异常。此方法向columnList添加新值。因此列数从3变为4.然后表会向列类询问最后一列,getColumnClass()返回第一行第4个元素的类。但是数据仍然包含3个元素的数组,因此数据中不存在索引3。

列列表的长度和数据列表中每个数组的长度应始终匹配:addColumn()应将数据列表中的每个数组替换为包含另一个元素的另一个数组。或者getValueAt()和其他方法应该处理它以返回默认值。