java.lang.ArrayIndexOutOfBoundsException

730 views Asked by At

I have multiple JSpinner which have items 1-10 , and one JTable. When the JSpinner is clicked, the value will be added to JTable. I want to get the row number so I can use it at setValueAt. But I get error when the JSpinner clicked more than once times.

Code

public void stateChanged(ChangeEvent e) {  // when JSpinner clicked
        int quantity = (int) ((JSpinner) e.getSource()).getValue();
        int rows = table.getRowCount();

        for (int i = 0; i < ELEMENTS; i++) {
            if (numspinner[i] == e.getSource()) {
                if (quantity == 1) {
                    System.out.println("Row"+rows);
                    dtm.addRow(new Object[] { foodLabel[i].getText(), quantity, price[i] * quantity });
                } else {
                    System.out.println("Row"+rows);
                    dtm.setValueAt(quantity, rows, 3); 
                }
            }
        }
    }

I clicked the same JSpinner more then once and get this output

Row1
Row2

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 2 >= 2
        at java.util.Vector.elementAt(Unknown Source)
        at javax.swing.table.DefaultTableModel.setValueAt(Unknown Source)
        at gui.FoodOrdering.stateChanged(FoodOrdering.java:250)
        at javax.swing.JSpinner.fireStateChanged(Unknown Source)
        at javax.swing.JSpinner$ModelListener.stateChanged(Unknown Source)
        at javax.swing.AbstractSpinnerModel.fireStateChanged(Unknown Source)
        at javax.swing.SpinnerNumberModel.setValue(Unknown Source)
        at javax.swing.JSpinner.setValue(Unknown Source)
        at javax.swing.plaf.basic.BasicSpinnerUI$ArrowButtonHandler.actionPerformed(Unknown Source)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)

Any help would be appreciated.

I have move some code and here the latest

  public void stateChanged(ChangeEvent e) {
            int quantity = (int) ((JSpinner) e.getSource()).getValue();
            int rows = 0;

            for (int i = 0; i < ELEMENTS; i++) {
                if (numspinner[i] == e.getSource()) {
                    if (quantity == 1) {
                        System.out.println("Row"+rows);
                        rows = table.getRowCount();
                        dtm.addRow(new Object[] { foodLabel[i].getText(), quantity, price[i] * quantity });
                    } else {
                        System.out.println(" The Row"+rows);
                        dtm.setValueAt(quantity, rows, 1); // obj,column,row
                    }
                }
            }   
    }

If the quantity is 1, it adds row as expected. When click the same JSpinner again, it always display 0!!!

1

There are 1 answers

1
Usagi Miyamoto On BEST ANSWER

I think your setup is incorrect.

You use quantity to "guess" the index. If quantity becomes 1, you add a new row to the table, if it is not 1, then you try to modify a row in the table. This has a few faults:

  • If there are more than one spinner, click each, and finally click any one of them a second time, which row should be modified?
  • If you click on a spinner twice, and then click on its - button to decrease and it becomes 1 once again, a new row would be added...

To address the above problems, there are a few options.
The most trivial one would be to implement your own TableModel not based on DefaultTableModel...
Another approach could be adding a column to your existing DefaultTableModel to be used for searching, and making it invisible. This column could be EG the JSpinner instance.

So try something like this:

public void stateChanged(ChangeEvent e) {
   final int quantity = (int) ((JSpinner) e.getSource()).getValue();
   final int rows = table.getRowCount();
   for (int row = 0; row < rows; ++row) {
      // look for the row that has the JSpinner in its last column
      if (dtm.getValueAt(row, 3) == e.getSource()) {
         // log out something
         System.out.println("Modifying row " + row);
         // modifying the value in the model
         dtm.setValueAt(quantity, row, 1); // obj, row, column
         return;
      }
   }
   // there was no row with this JSpinner, so we have to add it
   for (int i = 0; i < ELEMENTS; i++) {
      // looking for the "clicked" JSpinner
      if (numspinner[i] == e.getSource()) {
         // log out something
         System.out.println("Adding row " + rows);
         // adding a new row to the model
         dtm.addRow(new Object[] { foodLabel[i].getText(), quantity, price[i] * quantity, numspinner[i] });
         return;
      }
   }   
}