![]() |
|
Модераторы: LSD, AntonSaburov |
![]()
|
|
| User1302 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Здравствуйте, уважаемые форумчане!
Я новичок в Java. У меня возникла проблеммка с обновлением данных в JTable, кот. имеет моделью AbstractTableModel с List<> в качестве источника записей. Раньше не программировал интерфейс и возникшая ситуация ставит под сомнение правильность всей моей модели приложения. Попробую объяснить: 1. Есть обьекты, названные мною "Section", имеют свои поля (Код, Дата, Комментарий и проч.) Эти обьекты я хочу видеть в таблице JTable в отдельной строчке для каждого обьекта, где в столбцах - значения полей обьекта Section. Обьекты Section хранятся в массиве типа List<Section>. Массив List<Section> может пополняться новыми обьектами Section, также обьекты могут быть удалены из массива. 2. Таблица JTable использует AbstractTableModel, кот. берет данные из массива обьектов List<Section>. Вот примерный код, как это происходит:
3. События. Действия, кот. я хочу выполнять над обьектом Section: a) изменять его поля; Действия, кот. я хочу выполнять над массивом List<Section>: a) добавлять обьекты Section в массив; b) удалять обьекты Section из массива; Требуется, чтоб об этом узнавала таблица (модель) и при каждом изменении обьекта/списка обьектов обновлялись данные таблицы. Для простоты и по неопытности сейчас я это сделал так: Модель является подписчиком событий изменения обьекта Section - метод sectionUpdated(Section section){} и подписчиком событий изменения массива List<Section> - методы sectionAdded(Section section) и sectionWillBecomeRemoved(Section section). Соответственно в указанных методах вызываются методы модели AbstractTableModel - fireTableRowsUpdated(r, r);fireTableRowsInserted(r, r);fireTableRowsDeleted(r, r); А теперь собственно проблема: все работает, пока обновления происходят в одном потоке. Поскольку действия, производимые над обьектом Section занимают некот. время и над разными экземплярами Section могут одновременно выполняться действия, каждое действие выполняется в отдельном потоке. Когда действие завершается, обьект меняет свое состояние и об этом узнают все подписчики обьекта Section ч-з метод sectionUpdated(this), в их числе оказывается и моя модель таблицы. В отдельном потоке также могут производиться действия по добавлению и удалению в List<Section> обьектов. И вот когда происходит удаление подряд сразу нескольких обьектов Section - уведомляется об этом модель таблицы, выполняется fireTableRowsDeleted(r, r); и вылетает исключение: Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 Причем не всегда и при малом количестве обьектов (до десяти) все в порядке. Больше - обязательно исключение. Хотя пару раз не вылетало и при сотне обьектов. Блокировки synchronized не помогают. Думаю, проблема вот. в чем - из модели удаляются обьекты(строки) в том потоке, кот. это вызвал, а вот слушатели модели, в том числе JTable обновляются в другом потоке (EventDispatchThread???) и пока это происходит другой поток изменяет модель и уменьшает количество обьектов в массиве List<Section> и получается выход за пределы массива. Если я неправ, прошу меня поправить! В общем, прошу помощи в виде более-менее конкретных решений, типа "посмотри в сторону EventQueue.InvokeLater", или "SwingWorker", "EventDispatchThread". Перечисленные вещи крутятся в голове, но вплотную работать с ними не приходилось пока. Самое простое решение, кот. пришло в голову - запускать в самой модели отдельный поток на изменение модели, а удаляемые обьекты ставить в очередь. Но сейчас мне кажется это глупым. Буду очень признателен за все возможные варианты решений, в том числе радикальных, требующих пускай даже изменения всей модели приложения, ведь истина дороже! Повторяю, написать готовое решение я не прошу, достаточно совета, но за код тоже буду благодарен! На всякий случай прикрепляю рабочий вариант приложения, кот. сваял - очень сильно упрощенный вариант для удобства, но ошибка в нем присутствует. компилируется просто: javac Main.java, запускаетя тоже: java Main Всех заранее благодарю! Присоединённый файл ( Кол-во скачиваний: 3 )
Main.java.tar.gz 1,88 Kb |
|||
|
||||
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 4 Всего: 43 |
Да. Любые изменения модели следует выполнять в потоке EventDispatchThread. Тогда изменение и перерисовка изменения будут выполняться в одном потоке, т.е. последовательно, а не одновременно. |
|||
|
||||
| User1302 |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Попробовал сделать вот так:
В итоге вроде все хорошо работает. Правильно так делать? |
||||
|
|||||
| Skipy |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 487 Регистрация: 24.8.2006 Где: Москва, Россия Репутация: 4 Всего: 16 |
А sectionList у Вас - это модель таблицы? Не получится, что после получения события таблица обратится к модели для перерисовки, а Вы еще не удалили строку? Я бы поставил sectionList.remove(section) перед уведомлением.
Это сообщение отредактировал(а) Skipy - 18.11.2010, 11:31 |
|||
|
||||
| User1302 |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 23 Регистрация: 17.11.2010 Репутация: нет Всего: нет |
Думаю, вы правы - исправил, хотя работает и так, и так. sectionList - это список в модели, откуда строчки дергаются. ... Разобрался немного с моделью событий Swing. Запускать изменения интерфейса через "SwingUtilities.invokeLater()" мне кажется правильным решением. Если это не единственное решение, прошу показать еще варианты, если они есть. А в общем, думаю, тему можно считать закрытой. Спасибо COVD, Skipy, плюсики ставить еще не получается |
|||
|
||||
| jk1 |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 1168 Регистрация: 17.10.2008 Где: Санкт-Петербург Репутация: 21 Всего: 75 |
Модератор: Поставил -------------------- Opinions are like assholes — everybody has one |
|||
|
||||
![]()
|
| Правила форума "Java" | |
|
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |