0

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

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

2 回答 2

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();
}
于 2013-08-22T15:48:45.753 回答
1

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

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

于 2013-08-22T15:50:39.370 回答