Как обновить JTable на основе уведомления, полученного от длительной задачи в другом потоке? - PullRequest
1 голос
/ 28 октября 2010

У меня есть Observer TableModel, которая прослушивает некоторые изменения, выполненные в базе данных, и когда это так, вызывается метод обновления, приведенный ниже. Моя проблема заключается в том, как я должен предотвратить ошибки, такие как:

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.set(ArrayList.java:337)
at com.mysimpatico.memoplatform.persistenceui.MeaningsViewerTopComponent$DefaultTableModelImpl.update(MeaningsViewerTopComponent.java:108)

Я не понимаю, как SwingWorker мог бы помочь. Я выполняю долгосрочную задачу базы данных в отдельном потоке, но это вызывает метод (база данных сохраняется) в классе Observable, который уведомляет наблюдателей.

@Override
        public void update(Observable o, final Object arg) {
            final Meaning meng = (Meaning) arg;
            final int row;
            final boolean insert;
            synchronized (mengs) {
                if (mengs.contains(meng)) {
                    row = meng.getObjId();
                    mengs.set(row, meng);
                    insert = false;
                } else {
                    row = mengs.size();
                    mengs.add(row, meng); //last
                    insert = true;
                }
                try {
                    SwingUtilities.invokeAndWait(new Runnable() {

                    @Override
                    public void run() {
                        if (insert) {
                            fireTableRowsInserted(row, row);
                        } else {
                            fireTableRowsUpdated(row, row);
                        }
                    }
                });
            } catch (InterruptedException ex) {
                Exceptions.printStackTrace(ex);
            } catch (InvocationTargetException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

Ответы [ 3 ]

3 голосов
/ 28 октября 2010

Несмотря на запуск вставки / обновления TableModelEvent s в потоке диспетчеризации событий, вы фактически обновляете TableModel в зависимости от того, какой поток выполняет уведомление об обновлении базы данных.Это опасно, так как это означает:

  • Поток диспетчеризации событий может потенциально увидеть TableModel в несогласованном состоянии.
  • Поток диспетчеризации событий может пытаться отобразить TableModel поскольку поток уведомлений изменяет его.

Решение (теоретически) должно быть просто в случае перемещения вашего вызова на SwingUtilities.invokeAndWait за пределы блока кода, который начинается: synchronized(mengs).Кроме того, после того, как вы это сделаете, вы можете полностью удалить синхронизированное ключевое слово, так как весь доступ к вашей модели будет осуществляться на EDT.

Кроме того, я бы избегал использования Observer / Observableзанятия (для получения дополнительной информации см. мой ответ на этот вопрос );гораздо лучше определить доменные интерфейсы слушателей и классы событий (этот подкласс java.util.EventObject).

1 голос
/ 28 октября 2010

Ваши индексы верны?

java.lang.IndexOutOfBoundsException: Index: 1, Size: 1 

Вышеупомянутое утверждение говорит, что у вас есть только одна запись в списке массивов. Я не могу сказать, является ли ваш код "добавить" или "обновить". Но помните, что индексы ResultSet основаны на 1, а не на 0, так что, возможно, вам нужно вычесть 1 из всех значений строк?

0 голосов
/ 28 октября 2010

Один вариант использует org.jdesktop.application.Task. Вам нужно будет передать TableModel Задаче, а затем выполнить простой вызов TableModel.insert.

Примечание. Задача - это просто обертка вокруг потока.

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