Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: GUI и Java FX приложения > Правильно написать WorkerThread для Swing


Автор: Dims 20.12.2007, 14:51
Я написал несколько потоков, которые на заднем плане выполняют длительные операции, не мешая графическому интерфейсу. Однако, я обнаружил, что эти потоки всё же мешают интерфейсу.

Я думаю, что причина в том, что мои потоки постоянно постят в Свинг всякие сообщения. Например, один поток читает файл и заполняет структуру в памяти. При этом он постоянно сообщает окну прогресса о возникающих ошибках в данных. Делается это при помоши invokeLater, но, насколько я понимаю, настолько часто, что интерфейс всё же тормозит.

Может ли такое быть и как правильно поступить?

Я хочу, чтобы у меня список заполнялся прямо на ходу и было прям видно, как добавляются элементы и как меняется длина ползунка в полосе прокрутки.

Автор: COVD 20.12.2007, 16:40
Можно прореживать. Если загружается 10000 строк, то обновлять полосу прокрутки на каждой сотой строке, например. т.е. обновлять прогресс бар с шагом не меньше 1%.

Автор: Dims 21.12.2007, 17:39
С полосой прокрутки понятно. У меня в интерфейсе стоит таймер и интерфейс сам раз в секунду опрашивает поток и обновляет себе прогресс. Тут никаких проблем не возникает. А вот когда я хочу из параллельного потока асинхронно заполнить таблицу (большую) или список, то начинаются тормоза.

Автор: COVD 21.12.2007, 18:18
Цитата

У меня в интерфейсе стоит таймер и интерфейс сам раз в секунду опрашивает 


а я из первого сообщения понял наоборот, что поток, поставляющий данные, обновляет прогресс бар ("При этом он постоянно сообщает окну прогресса ...")

Цитата

А вот когда я хочу из параллельного потока асинхронно заполнить таблицу (большую) или список, то начинаются тормоза. 


Тут важно чтобы таблица не перерисовывалась на каждой добавленной строке. Перерисовывать таблицу имеет смысл не чаще, чем 1-2 раза в секунду. 



Автор: Dims 22.12.2007, 02:05
Ну в общем, поток обновляет, но не прогресс бар, а таблицу.

А как сделать, чтобы таблица перерисовывалась реже? Поток добавляет данные в модель таблицы, и делает это при помощи invokeLater. То есть, кладёт команды о добавлении в очередь Свинга. Когда очередь доходит, то данные добавдяются, модель таблицы автоматически уведомляет таблицу и она сама перерисовывается. Всё это в одном EventDispatchThread, как я понимаю. 

Как можно сделать, чтоб не перерисовывалась?

Автор: kkorsakoff 23.12.2007, 14:40
А как вы добавляете данные в модель? По идее если реализовать модель для таблицы как подкласс AbstractTableModel, то данные можно добавлять во "внутреннее хранилище данных модели". Тогда таблица автоматически не будет перерисовываться при каждом добавлении. А для перерисовки самостоятельно вызывать с некоторой периодичностью  fireTableRowsInserted(index, index)

Добавлено через 2 минуты и 13 секунд
Тогда добавлять данные можно даже не в EDT (если конечно обеспечить синхронизацию хранилища данных модели), а EDT только будет отрабатывать fireTableRowsInserted с такой периодичностью, с которой пожелаете.

Автор: Dims 23.12.2007, 20:41
Что такое EDT?

Ну да, у меня функция fire* автоматически вызывается в процедуре добавления данных в модель. Вроде бы, так должно быть. Если так не сделать, то, насколько я понимаю, будет проявляться мусор при перемещении окна?

Автор: kkorsakoff 24.12.2007, 13:19
EDT - Event Dispatch Thread

Мусора не будет, т.к. таблица еще знать не будет о новых строках.
Тут уж приходится выбирать: или gui, знающий о обновлениях в модели "порциями" или тормоза

Автор: COVD 26.12.2007, 05:03
согласен c kkorsakov. Таблица узнает об изменении модели по событию и это событие можно зажигать с прореживанием. Но это все замечательно, если строки просто добавляются в конец и никаких удалений. При удалении наверное надо сразу информировать. 

С другой стороны, в событии можно указать номер строки и перерисовываться должна не все таблица, а только необходимая строка. Ассортимент событий создан именно с целью избавления от тормозов. Но у меня не всегда получалось. Приходилось перерисовывать все.

Автор: LSD 26.12.2007, 12:38
Я бы сделал метод batchInsert() который бы вставлял не одну строку, а несколько.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)