Выбор потерян при перетаскивании мышью и одновременном обновлении в JTable - PullRequest
0 голосов
/ 28 марта 2012

В моем JTable я уже реализовал логику сохранения выбора во время обновлений. К сожалению, я думаю, что столкнулся с какой-то ошибкой. JTable обновляется фоновым потоком, который извлекает новые данные и добавляет / изменяет / удаляет их из модели таблицы.

Проблема проявляется только тогда, когда выполняется обновление при , когда пользователь перетаскивает мышь, чтобы выбрать строки в таблице. Что меня больше всего озадачивает, так это:

  • если я начинаю со строки и перемещаю мышь вверх , чтобы выбрать предыдущие строки, все работает отлично: выбор сохраняется при обновлениях, а действие пользователя продолжается правильно
  • Если я начинаю со строки и перемещаю мышь вниз , чтобы выбрать следующие строки, происходит сбой: при запуске обновления текущий выбор теряется, а новый выбор начинается со строки, находящейся под указатель при запуске обновления.

Есть какие-нибудь подсказки, почему это может происходить?


Это урезанная версия кода, о котором я говорю.

Я использую синхронизированную вручную TreeSet для обновления данных в фоновых потоках (см. update). Когда я закончу, я вызываю atomicSwapData, который создает массив, который будет использоваться getValueAt.

В updateTable вы можете увидеть, как я реализовал логику сохранения выбора, о которой я говорил ранее. Как видите, я пытался использовать метод EventQueue.invokeLater, но проблема все еще появляется. Обратите внимание, что все методы могут вызываться любым потоком, а не только EDT.

class MyDataModel extends AbstractTableModel {
    TreeSet<MyDataItem> ht = new TreeSet<MyDataItem>();
    MyDataItem[] _ht = MyDataItem.emptyArray();

    public Object getValueAt(int row, int col) {
        MyDataItem qdi;
        synchronized (_ht) {
            qdi = _ht[row];
        }
        // return one of the members of qdi, based on col
    }

    public void update(String qm, Collection<MyDataItem> toAdd) {
        HashSet<MyDataItem> toDrop = new HashSet<MyDataItem>();
        synchronized (ht) { 
            // do something with ht
        }
        swapData();
    }

    private void swapData() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                synchronized(_ht) {
                    MyDataItem[] tmp = ht.toArray(MyDataItem.emptyArray());
                    synchronized(tmp) {
                        _ht = tmp;
                    }
                } 
            }
        });
        updateTable();
    }

    private void updateTable() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                synchronized (_ht) {
                    int[] rowIndices = table.getSelectedRows();
                    fireTableDataChanged();
                    for (int row: rowIndices)
                        table.addRowSelectionInterval(row, row);
                }
            }
        });
    }
}

Ответы [ 2 ]

1 голос
/ 28 марта 2012

Для справки: пример постоянно обновляет TableModel из фонового потока, используя EventQueue.invokeLater().Он не проявляет аномалию, которую вы описываете.

0 голосов
/ 28 марта 2012

стандартное рисование для jtable сверху вниз, это может быть причиной того, что он ломается в одном направлении, а не в другом.

Вам нужно быть немного яснее и определить свои «разрывы»

Это просто рисует выбор неправильно? тогда вы сможете исправить это, заставив вашу таблицу выполнить полную перерисовку после обновления

...