small-j
small-j

Reputation: 309

Java Swing AbstractTableModel-IndexOutOfBounds exception when deleting a row

I'm making a Swing project. Probably, it's too big to be pasted here. I even tried to log a table.getSelectedRow() and it was showing a correct index. But somehow, when I press a delete button, which leads to the remove method called in this class, the selectedRow changes to -1 and I get an IndexOutOfBoundsException. Please, help. Here's the CarTableModelClass:

import javax.swing.table.AbstractTableModel;
import java.util.LinkedList;

public class CarTableModel extends AbstractTableModel {

public LinkedList<Car> cars=new LinkedList<Car>();
@Override
public int getRowCount() {
    return cars.size();
}

@Override
public int getColumnCount() {
    return 4;
}

@Override
public Object getValueAt(int row, int column){
    if((row>cars.size()-1) || (column>3) ){
        return null;
    }
    else {
        Car targetCar=cars.get(row);
        switch (column){
            case 0: {return targetCar.brand;}
            case 1: {return targetCar.year;}
            case 2: { return targetCar.volume;}
            case 3: {return targetCar.maxSpeed;}
            default: {return null; }
        }

    }
}

@Override
public Class<?> getColumnClass(int columnIndex){
    switch (columnIndex){
        case 0: {return String.class;}
        case 1: {return Integer.class;}
        case 2: { return Double.class;}
        case 3: {return Double.class;}
        default: {return Object.class; }
    }
}
@Override
public String getColumnName(int columnIndex){
    switch (columnIndex){
        case 0: {return "Brand";}
        case 1: {return "Year";}
        case 2: { return "Volume";}
        case 3: {return "Max Speed";}
        default: {return null; }
    }
}


@Override
public boolean isCellEditable(int rowIndex, int columnIndex){
    return false;
}

public void addRow(Car value)
{
    if(value!=null) {
        cars.add(value);
        fireTableDataChanged();
    }
}

public void update(int index, Car car){
    if((car!=null) &&(index>=0)&& (index<(cars.size()-1))){
        cars.set(index,car);
        fireTableRowsUpdated(index,index+1);
    }
}

public void remove(int index){
    if((cars!=null) &&(index>=0)&& (index<(cars.size()-1))){
        cars.remove(index);
        fireTableRowsDeleted(index,index+1);
    }
}
}

And here are the exceptions I get:

Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: -1, Size: 10
at java.util.LinkedList.checkElementIndex(LinkedList.java:555)
at java.util.LinkedList.get(LinkedList.java:476)
at CarTableModel.getValueAt(CarTableModel.java:26)
at MainWindow.lambda$new$0(MainWindow.java:51)
at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:184)
at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:164)
at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:211)
at javax.swing.DefaultListSelectionModel.removeIndexInterval(DefaultListSelectionModel.java:677)
at javax.swing.JTable.tableRowsDeleted(JTable.java:4509)
at javax.swing.JTable.tableChanged(JTable.java:4412)
at javax.swing.table.AbstractTableModel.fireTableChanged(AbstractTableModel.java:296)
at javax.swing.table.AbstractTableModel.fireTableRowsDeleted(AbstractTableModel.java:261)
at CarTableModel.remove(CarTableModel.java:83)
at Toolbar.actionPerformed(Toolbar.java:45)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6535)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
at java.awt.Component.processEvent(Component.java:6300)
at java.awt.Container.processEvent(Container.java:2236)
at java.awt.Component.dispatchEventImpl(Component.java:4891)
at java.awt.Container.dispatchEventImpl(Container.java:2294)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
at java.awt.Container.dispatchEventImpl(Container.java:2280)
at java.awt.Window.dispatchEventImpl(Window.java:2750)
at java.awt.Component.dispatchEvent(Component.java:4713)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
at java.awt.EventQueue.access$500(EventQueue.java:97)
at java.awt.EventQueue$3.run(EventQueue.java:709)
at java.awt.EventQueue$3.run(EventQueue.java:703)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.awt.EventQueue$4.run(EventQueue.java:731)
at java.awt.EventQueue$4.run(EventQueue.java:729)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
-1

UPD: Here's the lambda at line 51:

  table.getSelectionModel().addListSelectionListener((event)->
    {
        int row=table.getSelectedRow();
        formPanel.setSelectedRow(row);
        toolbar.setSelectedRow(row);
        System.out.println(row);
        formPanel.fill(
                model.getValueAt(row,0),
                model.getValueAt(row,1),
                model.getValueAt(row,2),
                model.getValueAt(row,3)
        );

    });

The thing is, I can't stop it from returning a -1.

Upvotes: 0

Views: 605

Answers (1)

whistling_marmot
whistling_marmot

Reputation: 3883

It looks like the row was successfully deleted by CarTableModel.remove, but then this invokes fireTableRowsDeleted, which in turn invokes some method in MainWindow that then invokes CarTableModel.getValueAt, but as the row has been deleted it throws an exception. You already test for values of row or column that are too large and then return from that method without doing anything. If you also test for negative values, does everything work?

Alternatively, as @JBNeizet says, the method on line 51 of MainWindow could test for negative values and not then call CarTableModel.getValueAt, but if getValueAt is being called from multiple places then it makes sense to do the parameter validation in the method itself.

Upvotes: 1

Related Questions