| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > 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() который бы вставлял не одну строку, а несколько. |