Last row always removed from DefaultTableModel, regardless of index

Solution 1:

The row obtained from columnAtPoint() is in view coordinates, while removeRow() assumes model coordinates. Quoting from the relevant tutorial section:

This distinction does not matter unless your viewed data has been rearranged by sorting, filtering, or user manipulation of columns.

If so, you will need to use convertRowIndexToModel(), described near the end of Sorting and Filtering, which advises:

When using a sorter, always remember to translate cell coordinates.

Also, consider using a ListSelectionListener instead of a MouseAdapter.

Addendum: Your implementation of getValueAt() continued to access the array supplied to the constructor, while the model's data was actually stored in the parent implementation. If you really need more control over the model's data structure, extend AbstractTableModel, as shown here.

import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

/** @see https://stackoverflow.com/a/11237205/230513 */
public class MainJF extends JFrame {

    private JTable tagsJT;
    private TagsSelectionTableModel model;
    private static int COLUMN_CHECK = 0;
    private static int COLUMN_TAG_NAME = 1;
    private static int COLUMN_TAG_ID = 2;
    private static int COLUMN_EDIT_TAG = 3;
    private static int COLUMN_DELETE_TAG = 4;

    public MainJF() {
        this.add(new JScrollPane(createTagsTable()));
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private JTable createTagsTable() {

        String[] columnNames = {"0", "Tag", "2", "3", "4"};

        Object[][] data = new Object[10][columnNames.length];
        for (int i = 0; i < data.length; i++) {
            data[i][COLUMN_CHECK] = false;
            data[i][COLUMN_TAG_NAME] = "Tag " + i;
            data[i][COLUMN_TAG_ID] = i;
            data[i][COLUMN_EDIT_TAG] = "edit";
            data[i][COLUMN_DELETE_TAG] = "delete";
        }
        model = new TagsSelectionTableModel(columnNames, data);
        tagsJT = new JTable(model);
        tagsJT.setRowSelectionAllowed(true);
        tagsJT.addMouseListener(new TagsTableMA());
        return tagsJT;
    }

    class TagsSelectionTableModel extends DefaultTableModel {

        public TagsSelectionTableModel(String[] columnNames, Object[][] data) {
            super(data, columnNames);
        }
    }

    class TagsTableMA extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent e) {
            Point p = e.getPoint();
            int row = tagsJT.rowAtPoint(p);
            int col = tagsJT.columnAtPoint(p);
            if (col == COLUMN_DELETE_TAG) {
                model.removeRow(row);
            }
        }
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new MainJF().setVisible(true);
            }
        });
    }
}

Solution 2:

Looking at the code of the removeRow(int) method of DefaultTableModel, it is clear that it will remove the row array at the corresponding index of the backing Vector:

 public void removeRow(int row) {
    dataVector.removeElementAt(row);
    fireTableRowsDeleted(row, row);
} 

(from java 6).

I can think of two possibilities:

  1. you've extended the DefaultTableModel and have changed the implementation of this method. (i doubt that this is the case - you probably would have admitted to this in your post)

  2. you have a custom renderer for the table, which paints the cell data based on the cell's row index.