![]() |
|
Модераторы: LSD, AntonSaburov |
![]()
|
|
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 4 Всего: 43 |
Такая проблема:
Внешний поток (команда с сервера) обновляет данные в таблице. Для примера, удаляет все строки. Выглядит примерно так:
т.е. есть момент, когда визуальное представление не соответствует модели. Если в этот момент пользователь кликнет строчку (а ее уже нет в модели), то получим исключение (ArrayOutOfBounds). Самое простое решение, наверное, поймать это исключение и игнорировать его. Немного хуже, если удаляются не все строчки, а только некоторые. Тогда есть вероятность, что пользователь кликнет на строке, а в модели ей будет соответствовать уже другая, потому что строки в модели сдвинулись. В этом случае и исключения не будет, просто будет выбрана неверная строка. Ощущение, что JTable не "заточен" на обновления "снаружи". Или я ошибаюсь, "сам дурак" и т.д.? |
|||
|
||||
| AlexeyVorotnikov |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 658 Регистрация: 18.6.2007 Где: Москва Репутация: 3 Всего: 18 |
-------------------- RTFM! Три источника и три составные части Java: The Java Language Specification, Java Platform API Specification, The Java Virtual Machine Specification |
|||
|
||||
| carper |
|
|||
|
Бывалый ![]() Профиль Группа: Участник Сообщений: 227 Регистрация: 2.3.2005 Репутация: 4 Всего: 8 |
COVD
1. Думаю, что внешний поток не должен сам ничего делать, он должен отдавать команды модели таблицы (фокус в том, что надо иметь именно свою модель, которая знает, как надо правильно реагировать на clear), а уж она отлично знает, что дальше делать, например, синхронизировать на объекте всякие там getRow. Т.е. мне кажется, что проблема несколько надумана. По поводу "Немного хуже, если удаляются не все строчки, а только некоторые. Тогда есть вероятность, что пользователь кликнет на строке, а в модели ей будет соответствовать уже другая, потому что строки в модели сдвинулись." Никакого отношения к JAVA это не имеет, я бы думал в плане, а почему это у меня строки удаляются так, что пользователь этого не видит или же успевает кликнуть не по той строке? Скорее всего здесь грубая ошибка логики программы. Как ни крутите, если у вас строки мутируют на глазах, то надо или смириться с этой фичей программы (например, на момент обновления взводить флаг, запрещающий/не реагирующий на щелчки по строкам), или что-то менять в интерфейсе. |
|||
|
||||
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 4 Всего: 43 |
AlexeyVorotnikov
Спасибо за ссылку на тюториал. Обратил внимание на SwingWorkers, которые пока никак не использовал. carper Спасибо! Полностью с вами согласен. Пришел к аналогичным выводам. |
|||
|
||||
| Dims |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1016 Регистрация: 21.11.2006 Репутация: 1 Всего: 11 |
В общем, насколько я понял, существует один поток, который называется EventDispatchThread, в котором выполняются все события, перерисовки и т.д. и т.п., то есть, всё графическое. Поскольку этот поток один, то заботиться о синхронизации не надо. Все методы Свинга небезопасны для многопоточности.
Если мы пишем поток, который должен посылать какие-то сообщения Свингу, то есть специальная статическая функция
эта функция в текущем потоке выполняет только одно дейтсвие -- кладёт объект Runnable в очередь на исполнение в потоке EventDispatchThread. Текущий поток сразу же продолжает работу, а поток EventDispatchThread, когда дойдёт до события, выполнит его в себе, то есть, синхронно с остальным Свингом. Недостаток этого метода в том, что если рабочий поток будет слишком быстро что-то делать, то он будет забивать очередь своими сообщениями и на нормальные сообщения Свинга будет оставаться меньше места. Чтобы обойти эту проблему, можно использовать либо метод speep, чтобы поток спал после помещения события, либо аналогичную функцию invokeAndWait которая задерживает вызвавший поток до окончания исполнения события в потоке EventDispatchThread. Добавлено через 1 минуту и 18 секунд Здесь использован "встрочный анонимный" класс. То есть, наследник от Runnable создался прямо в тексте вызова функции. Добавлено через 3 минуты и 2 секунды По моему, он только в 6-й джаве. То есть, обратной совместимости может не получиться. |
|||
|
||||
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 4 Всего: 43 |
Dims, если я правильно понял, вы полагаете, что если все делать через EventDispatchThread, то никаких проблем, кроме торможения GUI, не будет? Я думаю, даже это не поможет. Поможет только предложенное carper ("на момент обновления взводить флаг, запрещающий/не реагирующий на щелчки по строкам"), т.е. блокирование действий пользователя на время модификации модели таблицы и ее перерисовывания.
Например, в таблице три строки. Исполняется команда удалить вторую строку (пусть даже исполняется в EventDispatchThread ). Начинается все с удаления строки из модели. Начиная с этого момента пользователю должно быть запрещено "кликать" по строкам. Далее "зажигается" событие на перерисовку. Пока это событие не отработает ( пересчет индексов строк во внутреннем массиве таблицы и перерисовка таблицы - а это возможно еще одно событие в очередь) , пользователю не разрешено кликать, так как нарисованные строки уже не соответствуют модели. Если же ему разрешить и он кликнет на третью строку, то в очередь встанет событие, указывающее на третью строку. А она переместилась на место второй в модели. Результат - ArrayOutOfBounds exception при обращении к модели при обработке события. Как метко подметил carper, Java здесь ни при чем. Это сообщение отредактировал(а) COVD - 23.12.2007, 00:42 |
|||
|
||||
| Dims |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1016 Регистрация: 21.11.2006 Репутация: 1 Всего: 11 |
А какой в этом смысл? Щелчки по строкам -- это события в очереди EventDispatchThread. Пока EventDispatchThread занят удалением строки, щелчок по строке никак не может быть обработан, поскольку он ещё не смотрит, что у него там дальше в очереди.
Разве? Мне кажется, не так. Пользователь кликнет в районе третьей строки, в очередь встанет событие мыши, в котором будут указаны лишь двухмерные координаты точки щелчка. Лишь потом, когда это событий дойдёт до какого-то элемента, оно будет конвертировано в событие тыкания в строку в EventDispatchThread. Но это произойдёт только после того, как EventDispatchThread уже удалит строку из модели. Поэтому, в момент конвертации третьей строки уже не будет и произойдёт тоже самое, что произойдёт, если пользователь ткнёт ниже последней строки. |
|||
|
||||
| COVD |
|
|||
|
Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1655 Регистрация: 26.7.2005 Репутация: 4 Всего: 43 |
Наверное, тут вы правы. Если событие клика встало в очередь после событий удаления, то, действительно, это похоже на клик мимо таблицы. Но ведь редактирование, если реализуется в EventDispatchThread, состоит из двух последовательных событий - сначала редактирование модели, потом оно зажигает второе событие (fireTableChange...) . Так события от мыши могут пролезть между ними в очередь. Соответственно, эти мышиные события будут иметь координаты момента времени когда модель уже изменена, а таблица еще не перерисована, т.е. M и V не соответствуют друг другу. Надо поподробнее разобраться с EventDispatchThread. Спасибо. Это сообщение отредактировал(а) COVD - 26.12.2007, 14:37 |
|||
|
||||
![]()
|
| Правила форума "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. |