0

So I have a program that uses a JTable. Every time I want to delete a row and refresh the table it throws the following error.

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

I've seen similar questions to this question posted a few times:

jTable populating and refreshing ArrayIndexOutOfBoundsException

and

Refreshing JTable in Swing Gives Exception

and

ArrayIndexOutOfBoundsException when trying to empty a JTable

and a few others.

but I can't seem to decipher what's causing this for me. What my program does is that on start up the table is populated using data from a database. I am not inserting objects into the table; just string values directly from the database. My screen looks like this:

enter image description here

Selecting a row puts its values into the text boxes at the top of the frame. Ideally if I were to click delete the ID from the Office_ID field would then be used to delete a row from my database and the table would be refreshed to remove the row. The delete is working fine but instead of refreshing the table my program just throws the array index out of bounds error.

The code for building the table is here:

    private DefaultTableModel estateModel;
private JTextField IDField, addressField, suburbField, postcodeField, stateField, phoneField, faxField; 
private JTable estateTable;
private final JPanel containerPanel;
private JButton add, edit, view, delete, search, close;

public EstateScreen()
{
    containerPanel = new JPanel();
    containerPanel.setLayout(new BoxLayout(containerPanel, BoxLayout.Y_AXIS));
    addGridToPanel();
    addTableToPanel();
    addButtonsToPanel();
}


private void addTableToPanel()
{
    JPanel tablePane = new JPanel(new BorderLayout(2,2));
    String[] colNames = {"Office ID", "Address", "Suburb", "Postcode", "State", "Phone Number", "Fax Number"};
    estateModel = new DefaultTableModel()
    {
        @Override
        public boolean isCellEditable(int row, int column)
        {
            return false;
        }
    };
    estateModel.setColumnIdentifiers(colNames);
    estateTable = new JTable(estateModel);
    JScrollPane scroll = new JScrollPane(estateTable);
    tablePane.add(scroll);

    estateTable.getSelectionModel().addListSelectionListener(new ListSelectionListener()
    {
        @Override
        public void valueChanged(ListSelectionEvent event)
        {
            IDField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),0).toString());
            addressField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),1).toString());
            suburbField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),2).toString());
            postcodeField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),3).toString());
            stateField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),4).toString());
            phoneField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),5).toString());
            faxField.setText(estateTable.getValueAt(estateTable.getSelectedRow(),6).toString());
        }
    });

    containerPanel.add(tablePane);
}

My method for clearing the table:

    public void clearTable()
{
    estateModel.setRowCount(0);
    /*
   estateModel.removeTableModelListener(estateTable);
   while(estateModel.getRowCount() > 0)
   {
       estateModel.removeRow(0);
   }
   estateModel.addTableModelListener(estateTable);*/
}

and the actionListener for the delete button:

        gui.getEstateScreen().getDelete().addActionListener(new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            if(office.deleteByID(connB, gui.getEstateScreen().getID(), "office_id"))
            {
                gui.getEstateScreen().clearTable();
                populateEmployerScreen();
            }
            else
            {
                gui.getEstateScreen().outputAddError("Could not delete this office");
            }
        }
    });

and the populate Screen method as well for good measure:

    private void populateEmployerScreen()
{
    try
    {
        ResultSet rs = office.getAllData(connB);
        while(rs.next())
        {
            String[] data = new String[7];
            data[0] = Integer.toString(rs.getInt("OFFICE_ID"));
            data[1] = rs.getString("ADDRESS");
            data[2] = rs.getString("SUBURB");
            data[3] = Integer.toString(rs.getInt("POSTCODE"));
            data[4] = rs.getString("STATE");
            data[5] = rs.getString("PHONE_NUMBER");
            data[6] = rs.getString("FAX_NUMBER");

            gui.getEstateScreen().getModel().addRow(data);
        }

    }
    catch(SQLException s)
    {

    }

}

One last point. Interestingly, if I call the clear table method at the start of my program when no rows are selected it works fine. The moment I click on one of the rows however it begins throwing the array index out of bounds error. The only thing I can think of for this is that it somehow has trouble clearing a row when it is selected.

Can anyone help me with this?

Stack trace:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -1
at java.util.Vector.elementData(Vector.java:730)
at java.util.Vector.elementAt(Vector.java:473)
at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:649)
at javax.swing.JTable.getValueAt(JTable.java:2717)
at view.main.EstateScreen$2.valueChanged(EstateScreen.java:95)
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 javax.swing.table.DefaultTableModel.setNumRows(DefaultTableModel.java:321)
at javax.swing.table.DefaultTableModel.setRowCount(DefaultTableModel.java:339)
at view.main.EstateScreen.clearTable(EstateScreen.java:158)
at controller.RealEstateAgency$4.actionPerformed(RealEstateAgency.java:154)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
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:6516)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6281)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4872)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4698)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:740)
at java.awt.EventQueue.access$300(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:699)
at java.awt.EventQueue$3.run(EventQueue.java:697)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:713)
at java.awt.EventQueue$4.run(EventQueue.java:711)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:710)
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)
Community
  • 1
  • 1
user2787386
  • 303
  • 2
  • 7
  • 20
  • Can you add the stack trace? – Dakshinamurthy Karra Sep 05 '15 at 11:57
  • 1
    The issue might be with your selection listener, you are not checking whether the selectedRow method returns -1. – Dakshinamurthy Karra Sep 05 '15 at 11:59
  • 2
    Have you read the stack trace? It's not an ArrayIndexOutOfBoundsException at all, but a NumberFormatException thrown from EstateScreen.getID(), line 133. – JB Nizet Sep 05 '15 at 12:07
  • 1
    it is very obvious you you are trying to parse empty string to an integer with Integer.parseInt function in EstateScreen.getID just like JB Nizet mention – Adem Sep 05 '15 at 12:12
  • Sorry I posted the wrong stack trace. This was generated as I was playing around with my code. KDM is correct it seems; it is something to do with my selection listenerm – user2787386 Sep 05 '15 at 12:31

3 Answers3

2

It is better to follow the standard idioms of the framework/language. Instead of adding and removing the listener, add a guard to your valueChanged method.

public void valueChanged(ListSelectionEvent event) {
    int selectedRow = estateTable.getSelectedRow();
    if(selectedRow == -1) {
        // Most probably you should be clearing the text fields
        // here. At the least do a return
        return;
    }
    // Other code
}
Dakshinamurthy Karra
  • 5,353
  • 1
  • 17
  • 28
0

Big thanks to KDM for pointing out that the problem was with my ListSelectionListener.

Solved my issue by removing the listener before clearing the table and then adding it again afterwards.

public void clearTable()
{
    estateTable.getSelectionModel().removeListSelectionListener(listener);
    estateModel.setRowCount(0);
    estateTable.getSelectionModel().addListSelectionListener(listener);
}
user2787386
  • 303
  • 2
  • 7
  • 20
0

It's a bit late, but try adding the code line below before setting the text of the textboxes in ListSelectionListener

if (!e.getValueIsAdjusting() && estateTable.getSelectedRow() != -1)
Matteo Baldi
  • 5,613
  • 10
  • 39
  • 51
Hasan
  • 1