从JTable中删除对象时出现ArrayOutOfBoundsException

时间:2015-01-11 22:54:36

标签: java arrays swing jtable

我是Java的新手。我现在只学了半年了。现在我正在为一所学校项目工作,我已经完成了一个完整的墙:

我基本上是制作一个程序来管理自己的书籍。我有一个类“Books”,它保存book对象的数据。然后是“库”类,其中包含一个ArrayList of Books。对于TableModel,我使用扩展AbstractTableModel的类(“LibraryTableModel”)。然后我有一个显示表格的GUI类。

该表实际上有效,但有两个程序崩溃的情况:

当我将书籍添加到空库时,表格不会更新。但是,当我重新启动程序时添加了Book IS(我将Library类保存为.ser文件)。

然后我问的实例:我有一个从表中删除Books的按钮。 Button本身工作正常,但是当我删除一本书时,程序会抛出一个ArrayOutOfBoundsException。当我重新创建表格时,它会更新并删除书籍。这里有什么问题,为什么程序崩溃而不是更新表?

TableModel的代码:

public class LibraryTableModel extends AbstractTableModel
{
private String[] columnNames = {"Titel", "Autor", "Status", "Genre", "Verlag", "Seitenzahl", "ISBN", "Sprache", "Bewertung"};
private Object[][] data = {};
ArrayList<Book> lib;

public LibraryTableModel(Library l)
{
    //This Method returns the ArrayList in the Library class
    lib = l.getList();

    int libSize = lib.size();
    data = new Object[bib.size()][];

    for (Book b : lib)
    {
        int index = bib.indexOf(b);
        //(...)
        //CODE HERE gets all the data that is supposed to be displayed 
        //from each book in the ArrayList      
        Object[] oA = {tit, aut, sta, gen, ver, sei, isb, spr, bew};

        data[index] = oA;
    }
}

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) 
{
    return data[row][col];
    //When I try to remove a Book, the ArrayOutOfBounds Exception comes from here
}

public Class getColumnClass(int c) 
{
    return getValueAt(0, c).getClass();
}

public void setValueAt(Object value, int row, int col) 
{
    data[row][col] = value;
    fireTableCellUpdated(row, col);
}

public void removeRow(int row)
{
    lib.remove(row);
    fireTableRowsDeleted(row, row);
}

围绕表和tablemodel旋转的GUI类中的代码:

public class GUI implements ActionListener
{
JTable table;
LibraryTableModel model;
TableRowSorter<BibliothekTableModel> sorter;
Library lib;
JMenuItem deleteBook;

(...)通过.ser文件加载库

public void showTable() //This method is envoked in the GUI constructor through pressing a button
 {
    model = new LibraryTableModel(lib);
    table.setModel(model);

    deleteBook.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            int row = table.getSelectedRow();
            model.removeRow(row);

            //Code that saves the library at this point

            table.setModel(new LibraryTableModel(lib));
        }
    });

    popupMenu.add(deleteBook);
    table.setComponentPopupMenu(popupMenu);

    sorter = new TableRowSorter<BibliothekTableModel>(model);
    table.setRowSorter(sorter);
    JScrollPane scrollTable = new JScrollPane(table);

    //Next is code, that adds this ScrollPane to my Frame
 }

1 个答案:

答案 0 :(得分:1)

  

当我将书籍添加到空库时,表格不会更新。但是,当我重新启动程序时添加了Book IS(我将Library类保存为.ser文件)。

没有提供任何信息来说明这是如何工作的...以及.ser文件是什么?

  

然后我问的实例:我有一个按钮   从表中删除书籍。按钮本身工作正常,但是当我   删除一本书,该程序抛出一个ArrayOutOfBoundsException。当我   重新创建表,它会更新并删除书。是什么   问题在这里,为什么程序崩溃而不是更新表?

有两个问题......

首先,因为您在表上使用RowSorterJTable#getSelectedRow返回的可视行索引和模型中的物理行索引将不相同,您需要使用{ {3}}

int row = table.getSelectedRow();
row = table.convertRowIndexToModel(row);
model.removeRow(row);

//Code that saves the library at this point

其次,您要从lib删除该图书,但不更新内部缓存...

public void removeRow(int row)
{
    lib.remove(row);
    fireTableRowsDeleted(row, row);
}

模型没有使用lib作为数据的来源,而是使用您尚未更新的data数组。

虽然您可以简单地重建data数组,但更好的解决办法是摆脱它并直接使用lib,例如......

public class LibraryTableModel extends AbstractTableModel {

    private String[] columnNames = {"Titel", "Autor", "Status", "Genre", "Verlag", "Seitenzahl", "ISBN", "Sprache", "Bewertung"};
    private Object[][] data = {};

    private Library lib;

    public LibraryTableModel(Library l) {
        lib = l;
    }

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

    public int getRowCount() {
        return lib.getList().size();
    }

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

    public Object getValueAt(int row, int col) {
        Book book = lib.getList().get(row);
        Object value = null;
        switch (col) {
            case 0:
                value = ...;
                break;
            case 1:
                value = ...;
                break;
            case 2:
                value = ...;
                break;
            case 3:
                value = ...;
                break;
            case 4:
                value = ...;
                break;
            case 5:
                value = ...;
                break;
            case 6:
                value = ...;
                break;
            case 7:
                value = ...;
                break;
            case 8:
                value = ...;
                break;
        }
        return value;
//When I try to remove a Book, the ArrayOutOfBounds Exception comes from here
    }

    public Class getColumnClass(int c) {
        // Don't do this, know the actualy value and return it
        // Otherwise you could end up with a NullPointerException
        return getValueAt(0, c).getClass();
    }

    public void setValueAt(Object value, int row, int col) {
        // Use a simular technquie to getValueAt to extract the Book for the give
        // row and update the Book's attributes
        fireTableCellUpdated(row, col);
    }

    public void removeRow(int row) {
        lib.remove(row);
        fireTableRowsDeleted(row, row);
    }

}
相关问题