简体   繁体   中英

ArrayIndexOutOfBoundsException while adding row to datamodel

I apologize for asking a question that's been asked a lot in various forms, but I have yet to find a complete answer that works. All I'm trying to do is to append a row to a tablemodel. I've tried doing it in a lot of different ways but always run into similar issues (or sometimes new and exciting ones). Anyway, when I try to add the row I get an "ArrayIndexOutOfBoundsException" error. I've marked the line where the error occurs in the code below. I've also included the errors I've seen and debugging output I've been using. I'm aware I don't really need to extend the DefaultTableModel for what you see here, but this is a stripped down version that I've been working with to chase the bug.

Exception:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 2 > 0 at java.util.Vector.insertElementAt(Vector.java:594) at javax.swing.table.DefaultTableModel.insertRow(DefaultTableModel.java:374) at javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:350) at javax.swing.table.DefaultTableModel.addRow(DefaultTableModel.java:361) at SMC.RoleCard$1.actionPerformed(RoleCard.java:69) 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:6505) at javax.swing.JComponent.processMouseEvent(JComponent.java:3321) at java.awt.Component.processEvent(Component.java:627 0) at java.awt.Container.processEvent(Container.java:2229) at java.awt.Component.dispatchEventImpl(Component.java:4861) at java.awt.Container.dispatchEventImpl(Container.java:2287) at java.awt.Component.dispatchEvent(Component.java:4687) 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:4687) at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:729) 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. security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87) at java.awt.EventQueue$4.run(EventQueue.java:702) at java.awt.EventQueue$4.run(EventQueue.java:700) at java.security.AccessController.doPrivileged(Native Method) at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76) at java.awt.EventQueue.dispatchEvent(EventQueue.java:699) 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)

Debug Output:

There are 2 elements in roleData
roleData has 2 elements
Performing WHILE loop
tableData[0][0] is assigned ECC
tableData[0][1] is assigned 1
Performing WHILE loop
tableData[1][0] is assigned Portal
tableData[1][1] is assigned 2
Called getColumnCount()
Returned 2
tableDate has 2 columns and 2 rows.
Called getColumnCount()
Returned 2
Called getColumnName()
Returned Role
Called getColumnCount()
Returned 2
Called getColumnName()
Returned Sort Order
Called getColumnCount()
Returned 2
arg is :Role Data:
Clicked on Role
Called getColumnClass()
Called getColumnClass()
Called getColumnClass()
Called getColumnClass()
B: There are 2 rows in RoleTableModel
Add was pressed

Code:

package SMC;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

/**
 * @author Larry Krigbaum
 */
public class RoleCard
{
    public JPanel getRoleCard()
    {
        final JPanel roleCard = new JPanel();
        roleCard.setLayout(new BoxLayout(roleCard, BoxLayout.PAGE_AXIS));
        roleCard.setAlignmentX(Component.CENTER_ALIGNMENT);
        JPanel role_title = new JPanel();
        role_title.add(new JLabel(" "));
        role_title.add(new JLabel("Configure SAP Roles"));
        role_title.add(new JLabel(" "));
        roleCard.add(role_title);

        final JPanel role_table = new JPanel();
        String[] roleColumnNames = {"Role", "Sort Order"};
        ArrayList<Role> roleData = Role.loadRoleData();
        System.out.println("There are " + roleData.size() + " elements in roleData");
        //ArrayList<Role> roleData = null;
        final RoleTableModel roleTableModel = new RoleTableModel(roleColumnNames, roleData);
        JTable roleEditTable = new JTable(roleTableModel);
        roleEditTable.setAutoCreateRowSorter(true);
        //final DefaultTableModel roleTableModel = (DefaultTableModel) roleEditTable.getModel();
        //final JTable roleEditTable = getRoleTable();
        role_table.add(new JScrollPane(roleEditTable));                         // ScrollPane needed to show headers
        roleCard.add(role_table);

        JPanel buttonPanel = new JPanel();
        JButton addButton = new JButton("Add");
        addButton.setActionCommand("Add");
        JButton deleteButton = new JButton("Delete");
        deleteButton.setActionCommand("Delete");
        final JButton cancelButton = new JButton("Cancel");
        cancelButton.setActionCommand("Cancel");
        cancelButton.setEnabled(false);
        buttonPanel.add(addButton);
        buttonPanel.add(deleteButton);
        buttonPanel.add(cancelButton);
        roleCard.add(buttonPanel);
        addButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("B: There are " + roleTableModel.getRowCount() + " rows in RoleTableModel");
                System.out.println("Add was pressed");
                cancelButton.setEnabled(true);
                Object[] newRole = null;
                roleTableModel.addRow(newRole);
                //Object[] newRole = new Object[] {" ", " "};
                System.out.println("A: There are " + roleTableModel.getRowCount() + " rows in RoleTableModel");
                //roleTableModel.setRowCount((roleTableModel.getRowCount()) + 1);
                System.out.println("B: There are " + roleTableModel.getRowCount() + " rows in RoleTableModel");
                roleTableModel.fireTableRowsInserted(roleTableModel.getRowCount(), roleTableModel.getRowCount());
                roleTableModel.fireTableDataChanged();
            }
        });
        deleteButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("Delete was pressed");
                cancelButton.setEnabled(true);
            }
        });
        cancelButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                System.out.println("Cancel was pressed");
                cancelButton.setEnabled(false);
            }
        });

        return roleCard;
    }

class RoleTableModel extends DefaultTableModel
{
    private String[] roleColumnNames = {"Role", "Sort Order"};
    private Object[][] tableData;

    public RoleTableModel(String[] roleColumnNames, ArrayList<Role> roleData)
    {
        System.out.println("roleData has " + roleData.size() + " elements");
        tableData = new Object[roleData.size()][2];
        Role role = new Role();

        Collections.sort(roleData, Role.MakeComparator);
        Iterator rolesOrderByRole = roleData.iterator();
        int i = 0;
        while (rolesOrderByRole.hasNext())
        {
            System.out.println("Performing WHILE loop");
            role = (Role)rolesOrderByRole.next();
            tableData[i][0] = role.xrole;
            System.out.println("tableData[" + i + "][0] is assigned " + tableData[i][0]);
            tableData[i][1] = role.sortOrder;
            System.out.println("tableData[" + i + "][1] is assigned " + tableData[i][1]);
            i++;
        }
        System.out.println("tableDate has " + getColumnCount() + " columns and " + getRowCount() + " rows.");
    }

   @Override
    public int getColumnCount() 
    {
        System.out.println("Called getColumnCount()");
        System.out.println("Returned " + roleColumnNames.length);
        return roleColumnNames.length;
    }

    @Override
    public int getRowCount()
    {
       if (tableData == null)
           return 0;
       return tableData.length;
    }

    @Override
    public String getColumnName(int col) 
    {
        System.out.println("Called getColumnName()");
        System.out.println("Returned " + roleColumnNames[col]);
        return roleColumnNames[col];
    }

    @Override
    public Object getValueAt(int row, int col) 
    {
        return tableData[row][col];
    }

    @Override
    public Class getColumnClass(int c) 
    {
        System.out.println("Called getColumnClass()");
        return getValueAt(0, c).getClass();
    }

    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    @Override
    public boolean isCellEditable(int row, int col) 
    {
        System.out.println("Called isCellEditable()");
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        return true;
    }

    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    @Override
    public void setValueAt(Object value, int row, int col)
    {
        System.out.println("Called setValueAt()");
        tableData[row][col] = value;
        fireTableCellUpdated(row, col);
    }
}

You're creating a table model by extending DefaultTableModel. But instead of delegating to its methods to store the data, you store them in a separate array of data. And you override some methods and not others. The result is that sometimes, the methods of the superclass are used, that try to get and insert data in the vector held by the super class, and sometimes, the subclass methods are used that get and set values from/to the subclass array of data.

If you need to define a custom TableModel implementation, either extend AsbtractTableModel, and define everything as you want, or extend DefaultTableModel but don't add define any field. Only override methods that need to be overridden, and delegate to the superclass methods.

Except for getColumnClass() , I don't see any reason to override any method in DefaultTableModel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM