The accepted answer does not take modifier keys like ctrl or shift into account, yet they indicate that the current selection should not be replaced, but extended.
Also, I added multi-OS support by checking mousePressed
and mouseReleased
.
Following, you can find a complete example on how to adjust the selected rows, using the ListSelectionModel
, including MouseEvent#getModifiers
checks. After that, it is possible to open a (optional) JPopupMenu
.
JPopupMenu contextMenu = new JPopupMenu();
// ...
// add elements to the popup menu
// ...
table.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
handleRowClick(e);
if (e.isPopupTrigger()) {
doPop(e);
} else {
hidePop();
}
}
@Override
public void mouseReleased(MouseEvent e) {
if (e.isPopupTrigger()) {
doPop(e);
}
}
private void handleRowClick(MouseEvent e) {
ListSelectionModel selectionModel = table.getSelectionModel();
Point contextMenuOpenedAt = e.getPoint();
int clickedRow = table.rowAtPoint(contextMenuOpenedAt);
if (clickedRow < 0) {
// No row selected
selectionModel.clearSelection();
} else {
// Some row selected
if ((e.getModifiers() & InputEvent.SHIFT_MASK) == InputEvent.SHIFT_MASK) {
int maxSelect = selectionModel.getMaxSelectionIndex();
if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
// Shift + CTRL
selectionModel.addSelectionInterval(maxSelect, clickedRow);
} else {
// Shift
selectionModel.setSelectionInterval(maxSelect, clickedRow);
}
} else if ((e.getModifiers() & InputEvent.CTRL_MASK) == InputEvent.CTRL_MASK) {
// CTRL
selectionModel.addSelectionInterval(clickedRow, clickedRow);
} else {
// No modifier key pressed
selectionModel.setSelectionInterval(clickedRow, clickedRow);
}
}
}
private void doPop(MouseEvent e) {
if (table.getSelectedRowCount() == 0) {
return;
}
contextMenu.setVisible(true);
contextMenu.show(e.getComponent(), e.getX(), e.getY());
}
private void hidePop() {
contextMenu.setVisible(false);
}
});