0

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!!!

7
  • 1
    With zero based indices, like the JTable/TableModel, getRowCoun() return the number of rows, that is larger than the last row's index. EG if you have 3 rows, they are indexed as 0; 1; 2. There is no index 3... Commented Aug 27, 2017 at 15:40
  • @UsagiMiyamoto I thought the 2 is column ? Commented Aug 27, 2017 at 15:43
  • The stacktrace shows, that the setValueAt() method is called, and it is calling Vector.elementAt(), and this throws the exception. The setValueAt() method is called with column value of constant 3... Commented Aug 27, 2017 at 15:48
  • @UsagiMiyamoto How can I solve that ? I click the same JSpinner twice, and I get out Row 1 , Row 2, then crashed Commented Aug 27, 2017 at 15:51
  • 1
    It seems like at your first click, it adds the new row, but at your second click it tries to modify the cell at row index 2.. Commented Aug 27, 2017 at 16:03

1 Answer 1

1

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;
      }
   }   
}
Sign up to request clarification or add additional context in comments.

1 Comment

It display Adding row

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.