Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem with removing last row of JTable

This is my first time asking here so forgive me if something isn't appropriate, and sorry if my English isn't very good.

Well, to make it short, currently I'm developing a Java desktop app with Swing and I have a problem using table. I have rows with each row have a button to delete the row. Everything is okay (i can delete rows with no problem) until i try to delete the last row. The last row can be deleted but apparently there is an exception, something like this:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 4 >= 4
    at java.util.Vector.elementAt(Vector.java:427)
    at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:648)
    at javax.swing.JTable.setValueAt(JTable.java:2710)
    at javax.swing.JTable.editingStopped(JTable.java:4712)
    at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:125)

From the stack trace, it seems that "4" is my previously deleted last row index, but i have no idea how to deal with this. I already search for solution but i still can't solve it. Note that there are still other rows when i delete the last row, and after that i can't delete the others rows. The same exception also resulted when i click the delete button.

Oh. and I use removeRow() from DefaultTableModel to delete the row. Any help will be appreciated. Thanks.

EDIT These are the code I use.

public class ViewDetail extends JInternalFrame implements ActionListener {
    ...
    String column[] = { "Aaa", "Bbb", "Delete This"};

    tableModel = new DefaultTableModel();
    Object row[][] = new Object[size][column.length];

    //fill the data from db
    int r = 0;
    for (int i = 0; i < size; i++) {
    row[r][0] = ...;
    row[r][1] = ...;
    row[r][2] = "Delete";
    r++;
    }

    tableModel.setDataVector(row, column);
    table = new JTable(tableModel);

    tableColumn = table.getColumn("Aaa");
    tableColumn.setPreferredWidth(75);
    tableColumn = table.getColumn("Bbb");
    tableColumn.setPreferredWidth(75);
    tableColumn = table.getColumn("Delete This");
    tableColumn.setPreferredWidth(75);
    tableColumn.setCellRenderer(new ButtonRenderer());
    tableColumn.setCellEditor(new ButtonEditor(new JCheckBox());
     ...
}

public class ButtonRenderer extends JButton implements TableCellRenderer {
    public ButtonRenderer() {
        setOpaque(true);
    }
    public Component getTableCellRendererComponent(JTable table, Object value,
            boolean isSelected, boolean hasFocus, int row, int column) {
        if (isSelected) {
            setForeground(table.getSelectionForeground());
            setBackground(table.getSelectionBackground());
        } else {
            setForeground(table.getForeground());
            setBackground(UIManager.getColor("Button.background"));
        }
        setText((value == null) ? "" : value.toString());
        return this;
    }
}

public class ButtonEditor extends DefaultCellEditor {
    protected JButton button;
    private String label;
    private boolean isPushed;
    private JTable table;
    public ButtonEditor(JCheckBox checkBox) {
    super(checkBox);
    button = new JButton();
    button.setOpaque(true);
    button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            fireEditingStopped();
            }
        });
    }

    public Component getTableCellEditorComponent(JTable table, Object value,
        boolean isSelected, int row, int column) {
    if (isSelected) {
        button.setForeground(table.getSelectionForeground());
        button.setBackground(table.getSelectionBackground());
    } else {
        button.setForeground(table.getForeground());
        button.setBackground(table.getBackground());
    }
    label = (value == null) ? "" : value.toString();
    button.setText(label);
    isPushed = true;
    this.table = table;
    return button;
    }

    public Object getCellEditorValue() {
    if (isPushed) {
                  DefaultTableModel tableModel = (DefaultTableModel) table.getModel();                            
                  tableModel.removeRow(table.getSelectedRow());                
            }
            isPushed = false;
    return new String(label);
    }

    public boolean stopCellEditing() {
    isPushed = false;
    return super.stopCellEditing();
}

protected void fireEditingStopped() {
        super.fireEditingStopped();
    }
}
like image 808
ordinarydot Avatar asked Nov 29 '25 17:11

ordinarydot


1 Answers

Swing is trying to set the new value into the row you remove! Try moving the remove code into a Runnable and use invokeLater in the swing utility class to execute it.

like image 189
vickirk Avatar answered Dec 02 '25 06:12

vickirk