JavaSwingJTable and TableModel: Selection


Selection

JTable.changeSelection is broken because it relies on the stupid behaviour of DefaultListSelectionModel to change the selection from setLeadSelectionIndex(). That makes independent handling of selection and focus/anchor impossible. See FTable.java.

Selection of columns when clicking on the header

It has to be done with a MouseListener on the column header. Unfortunately it cannot be done totally LAF-independent, you have to make some assumptions about the behaviour of keyboard modifiers (changeSelection cannot be used, it wants a cell and not a whole row/column). The following is just a suggestion:

public void mouseClicked(MouseEvent e)
{
    JTableHeader header = table.getTableHeader();

    TableColumnModel columns = header.getColumnModel();

    if (!columns.getColumnSelectionAllowed())
        return;

    int column = header.columnAtPoint(e.getPoint());

    if (column == -1)
        return;

    int count = table.getRowCount();

    if (count != 0)
        table.setRowSelectionInterval(0, count - 1);

    ListSelectionModel selection = columns.getSelectionModel();

    if (e.isShiftDown())
    {
        int anchor = selection.getAnchorSelectionIndex();
        int lead = selection.getLeadSelectionIndex();

        if (anchor != -1)
        {
            boolean old = selection.getValueIsAdjusting();
            selection.setValueIsAdjusting(true);

            boolean anchorSelected = selection.isSelectedIndex(anchor);

            if (lead != -1)
            {
                if (anchorSelected)
                    selection.removeSelectionInterval(anchor, lead);
                else
                    selection.addSelectionInterval(anchor, lead);
                // The latter is quite unintuitive.
            }

            if (anchorSelected)
                selection.addSelectionInterval(anchor, column);
            else
                selection.removeSelectionInterval(anchor, column);

            selection.setValueIsAdjusting(old);
        }
        else
            selection.setSelectionInterval(column, column);
    }
    else if (e.isControlDown())
    {
        if (selection.isSelectedIndex(column))
            selection.removeSelectionInterval(column, column);
        else
            selection.addSelectionInterval(column, column);
    }
    else
    {
        selection.setSelectionInterval(column, column);
    }
}

For dragging it gets still more complicated (and interferes with column moving).


(C) 2001-2009 Christian Kaufhold (swing@chka.de)