ArrayIndexOutOfBoundsException with DefaultTableModel

Discussion in 'Java' started by Aloys Oberthuer, Apr 15, 2004.

  1. Hi everyone,

    i have got a problem with JTable. I created a small panel which includes
    a JTable (in a JScrollPane) with a DefaultTableModel as model and 3
    Buttons to add and remove rows and to clear the whole table. The problem
    is after deleting a row, and clicking on the row which is now the last,
    I always get ArrayIndexOutOfBoundsExceptions (see the StackTrace below).


    I create the Table as follows:

    DefaultTableModel dftM = new DefaultTableModel(2, 1);

    tbl = new JTable();
    tbl.setAutoCreateColumnsFromModel(false); // create my own ColumnModel
    tbl.setShowHorizontalLines(true);
    tbl.setShowVerticalLines(true);
    tbl.setModel(dftM);

    // build table column(s), custom renderer(s) and editor(s), etc.
    // see below



    All I do is invoke the following method in my code on a "delete row"
    button action:
    private void rowDelete() {
    int row = tbl.getSelectedRow();
    ((DefaultTableModel)tbl.getModel()).removeRow(row);
    }

    The table does redraw with one row less, but as I try to select another
    row, I always get the Exception. The same thing happens after clearing
    the Table which I do as follows:

    public void tableDataReset() {
    DefaultTableModel dftM = new DefaultTableModel(1, 1);
    tbl.setModel(dftM);
    }

    I.e. I do create a new DefaultTableModel and get the same problem. It
    looks like changing the model (deleting a row, replacing the model) did
    not really affect the model or leaves it in an inconsistent state, which
    I find especially strange with replacing the model. Sometimes after
    deleting a row and adding an empty new one the 'empty' row contains the
    content of the deleted row, which points in the same direction for me.
    I tried using tbl.tableChanged(new TableModelEvent(dftM)) but that did
    not help either. I have included the whole (executable) class and the
    stacktrace - any help would be greatly appreciated. I use J2SE 1.4.2 on
    a WindowsXp Sp1 System.

    Aloys




    CODE:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.table.*;


    public class SimpleTablePanel extends JPanel {

    private JTable tbl;
    private JScrollPane jsp;
    private JPanel pnlTable, pnlButtons;
    private JButton btAdd, btRemove, btClear;


    public SimpleTablePanel(String title, int tWidth, int tHeight) {
    super();

    createPanelTable(title, tWidth, tHeight);
    createPanelButtons();

    this.setLayout(new BorderLayout());
    this.add(pnlTable, BorderLayout.CENTER);
    this.add(pnlButtons, BorderLayout.SOUTH);
    }


    private void createPanelButtons() {
    // create Button Panel
    pnlButtons = new JPanel(new FlowLayout(FlowLayout.LEFT));

    btAdd = new JButton("Add");
    btAdd.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent aE){
    SimpleTablePanel.this.rowAdd();
    }
    });
    btRemove = new JButton("Del");
    btRemove.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent aE) {
    SimpleTablePanel.this.rowDelete();
    }
    });
    btClear = new JButton("Clr");
    btClear.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent aE) {
    SimpleTablePanel.this.tableDataReset();
    }
    });

    pnlButtons.add(btAdd);
    pnlButtons.add(btRemove);
    pnlButtons.add(btClear);
    }

    private void createPanelTable(String title, int tWidth, int tHeight) {
    pnlTable = new JPanel();

    DefaultTableModel dftM = new DefaultTableModel(2, 1);

    // next create Table
    tbl = new JTable();
    tbl.setAutoCreateColumnsFromModel(false); // create my own ColumnModel
    tbl.setShowHorizontalLines(true);
    tbl.setShowVerticalLines(true);
    tbl.setModel(dftM);

    // and build table column
    TableCellRenderer renderer = new DefaultTableCellRenderer();

    JTextField txt = new JTextField(20);
    txt.setBorder(null);
    TableCellEditor editor = new DefaultCellEditor(txt);

    ((DefaultCellEditor)editor).setClickCountToStart(1);

    TableColumn column = new TableColumn(0, tWidth, renderer, editor);
    column.setHeaderValue(title);
    tbl.addColumn(column);

    // and put it in a JScrollPane
    jsp = new JScrollPane(tbl);
    jsp.setPreferredSize(new Dimension(tWidth,tHeight));
    pnlTable.add(jsp, BorderLayout.CENTER);
    }

    private void rowAdd() {
    int row = tbl.getSelectedRow();
    ((DefaultTableModel)tbl.getModel()).insertRow(row+1, new String[] {""});
    }
    private void rowDelete() {
    int row = tbl.getSelectedRow();
    ((DefaultTableModel)tbl.getModel()).removeRow(row);
    }
    public void tableDataReset() {
    DefaultTableModel dftM = new DefaultTableModel(1, 1);
    tbl.setModel(dftM);
    }

    public static void main(String[] args) {

    JFrame jf = new JFrame("Testframe");
    jf.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent e) {System.exit(0);}
    });

    SimpleTablePanel jsF = new SimpleTablePanel("Table", 400, 300);
    jf.getContentPane().add(jsF, BorderLayout.CENTER);
    jf.pack();
    jf.setVisible(true);
    }
    }


    STACKTRACE:
    java.lang.ArrayIndexOutOfBoundsException: 2 >= 2
    at java.util.Vector.elementAt(Vector.java:431)
    atjavax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:633)
    at javax.swing.JTable.setValueAt(JTable.java:1794)
    at javax.swing.JTable.editingStopped(JTable.java:3167)
    atjavax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:124)
    at
    javax.swing.DefaultCellEditor$EditorDelegate.stopCellEditing(DefaultCellEditor.java:329)
    at javax.swing.DefaultCellEditor.stopCellEditing(DefaultCellEditor.java:214)
    at javax.swing.JTable.editCellAt(JTable.java:2510)
    at
    javax.swing.plaf.basic.BasicTableUI$MouseInputHandler.adjustFocusAndSelection(BasicTableUI.java:510)
    at
    javax.swing.plaf.basic.BasicTableUI$MouseInputHandler.mousePressed(BasicTableUI.java:494)
    at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:222)
    at java.awt.Component.processMouseEvent(Component.java:5097)
    at java.awt.Component.processEvent(Component.java:4897)
    at java.awt.Container.processEvent(Container.java:1569)
    at java.awt.Component.dispatchEventImpl(Component.java:3615)
    at java.awt.Container.dispatchEventImpl(Container.java:1627)
    at java.awt.Component.dispatchEvent(Component.java:3477)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:3483)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3195)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3128)
    at java.awt.Container.dispatchEventImpl(Container.java:1613)
    at java.awt.Window.dispatchEventImpl(Window.java:1606)
    at java.awt.Component.dispatchEvent(Component.java:3477)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)
    at
    java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
    at
    java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)
     
    Aloys Oberthuer, Apr 15, 2004
    #1
    1. Advertising

  2. Aloys Oberthuer

    Guest

    javadoc reades

    that get selectedrow returns
    Returns the index of the first selected row, -1 if no row is selected.
    so test for the -1 condition upon deleted.

    However, the problem may ly in the test case

    D selecting is not the same as editng
    Editing returns -1 also
    to test it out for yourself
    try clicking on the row the pressing the up arrow
    then delete without modifying your code
    it should work.

    Conclusion: need to test for no selection -1 = getSelecedRow
    upon delete and remember editing not same as selecting

    I may be wrong, I may; I may be right.
    Have a good day.
    peace be unto you.
     
    , Apr 16, 2004
    #2
    1. Advertising

  3. Aloys Oberthuer

    A.Buschmann Guest

    Hi Aloys,

    the stacktrace says, the problem comes from the "setValueAt()"-Method- but
    you are deleting,
    not editig.
    Or are you??
    With the DefaultTableModel, the "isCellEditable(int, int)"-Method returns
    simply "true".
    When you select a row with your mouse, it is open for edit. (Select row 2 of
    2)
    By clicking the delete-button, the edited-cell is not properly saved.
    The row where the edited cell is in becomes deleted.
    Now there is no row selected, but the JTable remembers that the first column
    in the second
    row was in edit-mode.
    When clicking on row one, the JTable sees: You are leaving the edited field.
    So JTable tries to save your edit. (In row 2 which does no longer exist)

    The exception will not occur, if you use the arrow-keys in the JTable:
    1. Click in row one
    2. Move with the down-key to row two
    The blinking cursor will vanish and the entire row becomes an
    highlighted border
    3. Delete row two. (Click on "Del"-Button)
    4. Click on row one.
    No Exception occurs.

    The DefaultTableModel is o.k., but the JTable does not realize, that the
    edited row has
    been removed.

    If you don't need to change the cells, extend DefaultTableModel and
    overwrite
    simply the "isCellEditable(int, int)"-Method:

    public boolean isCellEditable(int row, int column) {
    return false;
    }

    Else,
    you have to call the "stopCellEditing()"-Method from DefaultCellEditor-Class
    before you start with
    deleting the row.
    To get the CellEditor, the JTable has the "getCellEditor()"-Method.
    As far as I know, the "getCellEditor()"-Method returns "null", when
    no cell is edited.
    Your rowDelete() should look like this:
    private void rowDelete() {
    int row = tbl.getSelectedRow();
    if (row > -1) {
    DefaultCellEditor dce = (DefaultCellEditor)tbl.getCellEditor();
    if (dce != null) dce.stopCellEditing();
    ((DefaultTableModel)tbl.getModel()).removeRow(row);
    }
    }

    hope this helps.

    Alex
     
    A.Buschmann, Apr 17, 2004
    #3
  4. A.Buschmann wrote:
    > Hi Aloys,
    >
    > the stacktrace says, the problem comes from the "setValueAt()"-Method- but
    > you are deleting,
    > not editig.
    > Or are you??
    > With the DefaultTableModel, the "isCellEditable(int, int)"-Method returns
    > simply "true".
    > When you select a row with your mouse, it is open for edit. (Select row 2 of
    > 2)
    > By clicking the delete-button, the edited-cell is not properly saved.
    > The row where the edited cell is in becomes deleted.
    > Now there is no row selected, but the JTable remembers that the first column
    > in the second
    > row was in edit-mode.
    > When clicking on row one, the JTable sees: You are leaving the edited field.
    > So JTable tries to save your edit. (In row 2 which does no longer exist)
    >
    > The exception will not occur, if you use the arrow-keys in the JTable:
    > 1. Click in row one
    > 2. Move with the down-key to row two
    > The blinking cursor will vanish and the entire row becomes an
    > highlighted border
    > 3. Delete row two. (Click on "Del"-Button)
    > 4. Click on row one.
    > No Exception occurs.
    >
    > The DefaultTableModel is o.k., but the JTable does not realize, that the
    > edited row has
    > been removed.
    >
    > If you don't need to change the cells, extend DefaultTableModel and
    > overwrite
    > simply the "isCellEditable(int, int)"-Method:
    >
    > public boolean isCellEditable(int row, int column) {
    > return false;
    > }
    >
    > Else,
    > you have to call the "stopCellEditing()"-Method from DefaultCellEditor-Class
    > before you start with
    > deleting the row.
    > To get the CellEditor, the JTable has the "getCellEditor()"-Method.
    > As far as I know, the "getCellEditor()"-Method returns "null", when
    > no cell is edited.
    > Your rowDelete() should look like this:
    > private void rowDelete() {
    > int row = tbl.getSelectedRow();
    > if (row > -1) {
    > DefaultCellEditor dce = (DefaultCellEditor)tbl.getCellEditor();
    > if (dce != null) dce.stopCellEditing();
    > ((DefaultTableModel)tbl.getModel()).removeRow(row);
    > }
    > }
    >
    > hope this helps.
    >
    > Alex



    Thanks a lot, invoking the stopCellEditing() method does indeed solve the problem. Now my rowDelete() method does look
    like this, which actually does pretty much the same (I'd say your's is even a little more elegant) :
    private void rowDelete() {
    if(tbl.getCellEditor() != null)
    ((DefaultCellEditor)tbl.getCellEditor()).stopCellEditing();

    int row = tbl.getSelectedRow();
    if((row >= 0) && (tbl.getRowCount()>1)) {
    DefaultTableModel tm = (DefaultTableModel)tbl.getModel();
    tm.removeRow(row);
    tbl.repaint();
    }
    }

    Searching the web I got the idea that quite a lot had the same problem, wonder why some things have to be so complicated.
    Thanks, Aloys
     
    Aloys Oberthuer, Apr 22, 2004
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Deshaies
    Replies:
    3
    Views:
    4,554
    Deshaies
    Apr 20, 2004
  2. Parvinder
    Replies:
    2
    Views:
    7,019
    PuneetNanda9
    Jun 15, 2012
  3. Cyril Dex

    DefaultTableModel

    Cyril Dex, Sep 20, 2004, in forum: Java
    Replies:
    2
    Views:
    3,712
    Nigel Wade
    Sep 21, 2004
  4. Peter
    Replies:
    2
    Views:
    3,014
    Andrew Thompson
    Jan 4, 2005
  5. Peter

    extends DefaultTableModel ?

    Peter, Jan 3, 2005, in forum: Java
    Replies:
    0
    Views:
    676
    Peter
    Jan 3, 2005
Loading...

Share This Page