Java: Как перетащить строки JTable без использования TransferHandler? - PullRequest
0 голосов
/ 21 сентября 2019

В Java JTable по умолчанию не предлагает функцию перетаскивания JTable строк для переупорядочения таблицы.Многие ответы, которые я вижу в Интернете, предполагают, что вы должны использовать собственную реализацию TransferHandler для достижения этой цели.Однако я считаю, что это сильно усложняет ситуацию, и для этого должен быть более простой способ.Кто-нибудь может дать советы о том, как более эффективно перетаскивать строки таблицы для переупорядочения таблицы?

1 Ответ

1 голос
/ 21 сентября 2019

Чтобы добиться такого поведения, вы можете использовать комбинацию 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) на сортировщике вашего стола.

...