| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java: GUI и Java FX приложения > Обьясните пожалуйста что такое invokeLater() ? |
| Автор: 604 27.4.2005, 14:35 |
| Обьясните пожалуйста что такое SwingUtilities.invokeLater() как его использовать и для чего это нужно? |
| Автор: batigoal 27.4.2005, 14:39 | ||||
Добавлено @ 14:41
Хотя вот мне это все ничего не объяснило. Подождем кого-нибудь умного... Добавлено @ 14:43 Видимо, запускает код немедленно, не дожидаясь, пока отработает код обработки событий, находящихся в очереди. Пример, когда это может понадобиться, придумать не могу. |
| Автор: 604 27.4.2005, 14:46 | ||
У меня выдает: Hello World on Thread[AWT-EventQueue-0,6,main] This might well be displayed before the other message. А должно быть наоборот? |
| Автор: batigoal 27.4.2005, 15:25 | ||||
Посмотри, какой странный результат я получил при выполнении такого кода:
Результат привожу полностью:
ох уж мне эта многопоточность... |
| Автор: AntonSaburov 27.4.2005, 15:35 |
| Это в принципе идея того же треда, но более изощренная. В общем виде - твой обработчик будет поставлен в очередь событий для AWT и будет обработан уже после очередных задач. В твоем случае событий там само собой нет, поэтому выполняем практически сразу. |
| Автор: batigoal 27.4.2005, 15:43 | ||||||
Если заменить
на обычный
то получим
Логично. Но применения этой возможности я вске равно не вижу. Разве что, как там написано, изменение GUI. |
| Автор: AntonSaburov 27.4.2005, 15:45 | ||
Именно для этого и используется. Например ты хочешь изменить какие-то картинки на форме, но делать это прямо в обработчике например для кнопки - дело не очень мудрое. Графика и так в отдельном треде - потому результат может быть совсем странный. А так ты уверен, что твои изменения будут вызваны в нужное время. И самое главное это не завесит обработчик - ты из invokeLater выходишь сразу. |
| Автор: batigoal 27.4.2005, 15:49 |
| Спасибо. Теперь нам с 604 все понятно. |
| Автор: Guest 27.4.2005, 16:41 |
| Lamer George УУпс пока еще не совсем понятно Можно еще пример, совсем на пальцах если незатруднит, или от вас AntonSaburov |
| Автор: batigoal 27.4.2005, 16:59 |
| Ну если на пальцах, то так: Помимо основного потока программы (понятие потока расшифровывать не надо?), в ней существуют еще некоторые, "неявные" потоки, в частности, поток-диспетчер событий. Назначение его состоит в том, чтобы обрабатывать события интерфейса. Если мы будем клацать по интерфейсу слишком быстро (1000 кликов по кнопке в секунду Теперь допустим, что у нас есть ситуация, когда нам необходимо перестроить интерфейс во время выполнения программы. Тогда это лучше сделать не немедленно, а тогда, когда мы обработаем всю скопившуюся у нас на входе очередь событий. Тогда мы используем invokeLater() и наш поток выполнится лишь тогда, когда очередь очистится (пример 1). |
| Автор: Stampede 27.4.2005, 20:24 | ||
Объясняю. Так уж устроен AWT, что все оконные события выстраиваются в одну очередь и обрабатываются по порядку. Пока событие полностью не обработано, никаких видимых результатов на экране не будет. В большинстве случаев обработка тривиальная, все происходит быстро и никаких тормозов не заметно. Но иногда нажатие кнопки или еще какое-нибудь пользовательское действие запускает операцию, которая занимает ощутимое время: типа мощное вычисление, установка соединения или чтение/запись большого файла. Допустим, это длится одну минуту. Если ничего специально не предпринимать, юзер будет целую минуту тупо сидеть перед застывшим экраном и вообще не иметь ни малейшего понятия, что происходит. При этом вы в коде обработчика можете ему там выводить всякие надписи, показывать индикатор прогресса и т. д. - все псу под хвост, потому как отобразится это дело только когда вы вернете управление потоку, а это произойдет не раньше, чем ваша долгая операция так или иначе завершится. Выход тут в том, чтобы создавать для таких долгих штук отдельный поток и там их выполнять, а управление главному потоку обработки событий возвращать немедленно. Теперь вроде все нормально, но вы хотите, допустим, по мере продвижения операции выводить сообщения о прогрессе. Так вот, если это делать напрямую, типа там JTextArea.append("Еще один демульгатор был эксторнизирован\n"), то это чревато неприятностями, потому как многие классы в AWT/Swing не являются thread-safe (ну если вам так уж не нравятся оригинальные английские термины, пускай будут потокобезопасными Чтобы обновления такого рода были потокобезопасными, рекомендуется делать их потокобезопасным образом: заворачивать в объект типа Runnabe и подсовавать диспетчеру событий через посредство SwingUtilities.invokeLater(). Тогда, если в данный момент никакие кнопочки не нажимаются и ничего не происходит, обновление сразу и перерисуется, а если что-то уже обрабатывается, ваш запрос на обновление будет поставлен в очередь и получит возможность выполниться, когда до него дойдет очередь. Вот зачем, собственно, нужен invokeLater(). |
| Автор: batigoal 27.4.2005, 20:55 | ||
Не всем, только мне. Спасибо. |
| Автор: 604 28.4.2005, 10:54 | ||
| Всем спасибо! Написали очень понятно! Прошу прошения, но снова понял не до конца Написал небольную программку, и не могу понять в чем тут проблема если я не использую этот invokeLater, и где конкретно в этом случае надо применять invokeLater?
Вроде понимаю что такое очередь и что что такое поток, но вот где применять и для какого случая этот invokeLater не понимаю |
| Автор: Stampede 28.4.2005, 11:44 | ||||
Код не проверял, но выглядит вполне работающим. Проблема может быть в следующем. Вот у тебя по нажатию кнопки идет инкремент числа, которое отображается в JLabel. Поскольку ширина графического представления чисел разная, у тебя при изменении текста лэйбла будет каждый раз происходить перераскладывание компонентов в соответствии с политикой LayoutManager'а. Если при этом ничего другого на экране не происходит, то ничего страшного. Но что если ты в этот же момент захотел потянуть какой-нибудь сплиттер? Тут и могут произойти нежелательные казусы в виде висячих фрагментов элементов интерфейса (George, ничего, что я говорю по английски? Ну и вот, а если ты хочешь этого избежать, то ты делаешь вот так:
Тут надо понимать, что тот Runnable, который подсовывается диспетчеру событий, не имет никакого отношения к потоковости. Это просто удобный обобщенный способ вызова некой обезличенной беспараметерной функциональности. Поэтому у тебя будет один run() для твоего потока, где происходят всякие интересные штуки, а другой - для диспетчера, чтобы он знал, как инициировать действия по перерисовке. И произойдет это теперь уже синхронным, а не асинхронным образом. Так понятнее? |
| Автор: Metal_Heart 28.4.2005, 11:49 |
| Спасибо Stampede, хорошо объясняешь, но я как и Lamer George не люблю буржйских слов в русском, язык должен быть по возможности - чистым и не важно какой, а смешивать - это не красиво.. |
| Автор: 604 28.4.2005, 11:56 |
| Stampede Короче говоря, если я правильно понял |
| Автор: batigoal 28.4.2005, 14:30 |
| 604 Да. Stampede Как раз сейчас - без претензий |
| Автор: 604 28.4.2005, 15:10 |
| Урра! Всем спасибо что научили! |
| Автор: Stampede 30.4.2005, 22:48 | ||
Вспомнил еще один анекдот: - Зачем использовать буржуйское слово фаерволл, когда есть хорошее русское слово - брандмауэр |
| Автор: Metal_Heart 3.5.2005, 09:17 |
| |
| Автор: AntonSaburov 3.5.2005, 12:31 |
| Модератор: Уже флуд начался - не увлекайтесь. |
| Автор: Zandr 6.5.2005, 06:19 | ||
Запоздало, но все же. Вот когда начнут происходить странные вещи с перерисовкой, поведением менюшек (например после вызова диалога из обработчика менюшки) и прочие, вот тогда начинайте вспоминать про invokeLater(). Кстати, многие простые вещи типа label.setText() все-таки thread-safe. Metal_Heart, Вставил я как-то свой ПЗКП в ПКДПЗУ, закатал туда фильм... Технология!.. Я к тому что ты знаешь где границы в употреблении английских слов, сокращений в русском? (давайте, люди, аббревиатуру API переведем на русский и будем употреблять её) А в сообщениях на форуме? Здесь люди пишут не за деньги. Не говорите им как писать и они не скажут вам, куда пойти. Модератор, и все кого обидел - сорри за этот выпад. Накипело. |