How to make JTable by clicking on unselected, drag, and not select

If you have JTable installed with table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) and then you drag a row that is not selected, it starts to select multiple rows. We do not want this behavior. We want to do this, if you click on node, even if it is not already selected, it will start dragging it.

We need a multiple choice mode, so setting it to one choice (which leads to the desired behavior) is not an option.

Update: at the moment, it seems that this will require some type of ugly hack, since the logic is in the private method BasicTableUI $ Handler.canStartDrag

+4
source share
5 answers

I found one possible solution. You are binding mouse listeners so that you can lie to the isCellSelected call while calling canStartDrag.

Subclass of JTable (or in my case JXTreeTable). In the constructor, call this:

 private void setupSelectionDragHack() { // Bracket the other mouse listeners so we may inject our lie final MouseListener[] ls = getMouseListeners(); for (final MouseListener l : ls) { removeMouseListener(l); } addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { // NOTE: it might not be necessary to check the row, but... I figure it safer maybe? mousingRow = rowAtPoint(e.getPoint()); mousingInProgress = true; } }); for (final MouseListener l : ls) { addMouseListener(l); } addMouseListener(new MouseAdapter() { @Override public void mousePressed(final MouseEvent e) { mousingInProgress = false; } }); } 

And then you need the following:

 @Override public boolean isCellSelected(final int row, final int column) { if (mousingInProgress && row == mousingRow) { // Only lie to the canStartDrag caller. We tell the truth to everyone else. final StackTraceElement[] elms = Thread.currentThread().getStackTrace(); for (int i = 0; i < 3; i++) { if (elms[i].getMethodName().equals("canStartDrag")) { return mousingInProgress; } } } return super.isCellSelected(row, column); } 

It's an ugly hack in many ways, but ... for now it works.

+3
source

Unfortunately, none of the other answers worked for me.

So, I made my own hack / fix for the problem (I am posting it here for others with the same problem):

 public class SFixTable extends JTable { private static final long serialVersionUID = 1082882838948078289L; boolean pressed = false; int currSRow = -100; public SFixTable(TableModel dm) { super(dm); } public SFixTable() { super(); } public SFixTable(Vector<?> rowData, Vector<?> columnNames) { super(rowData, columnNames); } @Override protected void processMouseEvent(MouseEvent e) { int row = rowAtPoint(e.getPoint()); int col = columnAtPoint(e.getPoint()); if (SwingUtilities.isLeftMouseButton(e) && !e.isShiftDown() && !e.isControlDown()) { boolean isDragRelease = (e.getID() == MouseEvent.MOUSE_RELEASED) && row != currSRow; boolean isStartClick = (e.getID() == MouseEvent.MOUSE_PRESSED); if (row >= 0 && col >= 0) { if (isStartClick) { super.changeSelection(row, col, false, false); } else if (isDragRelease) { super.changeSelection(currSRow, col, false, false); } } pressed = (e.getID() == MouseEvent.MOUSE_PRESSED); if (pressed) { currSRow = row; } else { currSRow = -100; } } super.processMouseEvent(e); } @Override public boolean isCellSelected(int row, int col) { return (pressed)? (row == currSRow) : super.isCellSelected(row, col); } } 
+3
source

This is mistake:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6349223

and, as you already suggested, this requires some ugly hack. Here is one (not from me, but from Aephyr user on old sun forums that didn't survive the transition to OTN)

  table = new JTable() { // fix for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6349223 // requirement is the option to turn off drag-selection if dragEnabled // fix posted in sun dev forum by Aephyr // http://forums.sun.com/thread.jspa?threadID=5436355&tstart=0 private boolean pressed; @Override protected void processMouseEvent(MouseEvent e) { pressed = e.getID() == MouseEvent.MOUSE_PRESSED; if (pressed && !e.isShiftDown() && !e.isControlDown()) clearSelection(); try { super.processMouseEvent(e); } finally { pressed = false; } } @Override public boolean isCellSelected(int row, int col) { return pressed ? true : super.isCellSelected(row, col); } }; 
+1
source

As is the case with kleopatra, but this seems to cope with several problems with the previous one - you can control the click to add and remove elements from several options, and you can successfully drag and drop a group with several choices. I only tested this with ETable / Outline from NetBeans, but should work with regular JTable.

 table = new JTable() { private boolean inPress = false; @Override protected void processMouseEvent(MouseEvent e) { inPress = e.getID() == MouseEvent.MOUSE_PRESSED && e.getButton() == MouseEvent.BUTTON1 && !e.isShiftDown() && !e.isControlDown(); try { super.processMouseEvent(e); } finally { inPress = false; } } @Override public boolean isCellSelected(int row, int col) { boolean selected = super.isCellSelected(row, col); if (inPress) { if (!selected) clearSelection(); return true; } return selected; } }; 
+1
source

If you want to drag an unselected row into a single JTable selection, setting the table selection model to SINGLE_SELECTION mode is not enough, you also need to set the column model selection mode.

 JTable table = new JTable(); table.getSelectionModel() .setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.getColumnModel().getSelectionModel() .setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 
+1
source

All Articles