Чтобы добиться такого поведения, вы можете использовать комбинацию MouseListener
и MouseMotionListener
.DefaultTableModel
предоставляет функциональность, с помощью которой вы можете перевести Point
события в строку, в которой это событие произошло.Используя эту функциональность, мы можем эффективно перетаскивать строки таблицы.Пример кода ниже показывает базовую реализацию, с которой строки таблицы перетаскиваются в режиме реального времени.Обратите внимание, что свойства table
и tableModel
специально ослаблены: мы не хотим, чтобы MouseHandler
сохранял строгое указание либо на table
, либо на tableModel
.
public class MouseHandler implements MouseListener, MouseMotionListener {
private Integer row = null;
private final WeakReference<JTable> table;
private final WeakReference<DefaultTableModel> tableModel;
public MouseHandler(JTable table, DefaultTableModel model) {
this.table = new WeakReference<>(table);
this.tableModel = new WeakReference<>(model);
}
@Override
public void mouseClicked(MouseEvent event) {}
@Override
public void mousePressed(MouseEvent event) {
JTable table;
if((table = this.table.get()) == null) {
return;
}
int viewRowIndex = table.rowAtPoint(event.getPoint());
row = table.convertRowIndexToModel(viewRowIndex);
}
@Override
public void mouseReleased(MouseEvent event) {
row = null;
}
@Override
public void mouseEntered(MouseEvent event) {}
@Override
public void mouseExited(MouseEvent event) {}
@Override
public void mouseDragged(MouseEvent event) {
JTable table;
DefaultTableModel tableModel;
if((table = this.table.get()) == null || (tableModel = this.tableModel.get()) == null) {
return;
}
int viewRowIndex = table.rowAtPoint(event.getPoint());
int currentRow = table.convertRowIndexToModel(viewRowIndex);
if(row == null || currentRow == row) {
return;
}
tableModel.moveRow(row, row, currentRow);
row = currentRow;
table.setRowSelectionInterval(viewRowIndex, viewRowIndex);
}
@Override
public void mouseMoved(MouseEvent event) {}
}
* 1012.* Это, на мой взгляд, намного более чистая и более дружественная реализация, чем большинство предложений, в которых используется
TransferHandler
.
Обновление от 22 сентября 2019 г. 11.51 CEST Как предложено @ MadProgrammer , оригинальный пример имеет проблемы при работе с отфильтрованными / отсортированными таблицами.Пример теперь обновлен, чтобы также поддерживать их.При перемещении строк в отсортированной таблице перемещенная строка будет вставлена на один индекс после следующей видимой строки.Это означает, что в базовой модели строка может перемещаться более чем на один индекс за раз.
Важное замечание: Если вы хотите убедиться, что ваша таблица остается отфильтрованной / отсортированной после перемещения строки, убедитесь, что вы вызвалиsetSortsOnUpdates(true)
на сортировщике вашего стола.