Как могут работать диалоги Swing?
Если вы откроете диалог в Swing, например JFileChooser, он будет несколько похож на этот псевдокод:
swing event thread {
create dialog
add listener to dialog close event {
returnValue = somethingFromDialog
}
show dialog
(wait until it is closed)
return returnValue
}
Мой вопрос: как это может работать? Как видите, поток ожидает возвращения до закрытия диалогового окна. Это означает, что поток событий Swing заблокирован. Тем не менее, можно взаимодействовать с диалогом, который AFAIK требует, чтобы этот поток работал.
Итак, как это работает?
Ответы
Ответ 1
Это AWT-нить, а не Swing's.
В любом случае AWT запускает цикл отправки в show
. Ввод событий в заблокированные окна блокируется. Перерисовывать события, события для разблокированных окон и общие события отправляются как обычно.
Вы можете увидеть это, добавив строку:
Thread.dumpStack();
в четную обработку для модального диалога или более легко из командной строки с помощью jstack
или использовать ctrl-\
/ctrl-break
в окне команд приложения.
Библиотека Foxtrot злоупотребляет этим, чтобы обеспечить более процедурную (в отличие от управляемой событиями) модель. Он также используется WebStart/Java PlugIn для предоставления диалогов для служб JNLP и других при вызове из приложения EDT.
Ответ 2
Существующий поток диспетчеризации событий блокируется, и поэтому swing создает другой поток, который накачивает события. Это будет поток отправки событий на время диалога.
Swing создает отдельный собственный поток для переадресации сообщений о состоянии ОС. Это отдельно от потока событий AWT.
В Windows вы видите эти потоки
"AWT-Windows" - the native UI thread
"AWT-EventQueue-0" - the current AWT event dispatch thread
РЕДАКТИРОВАТЬ: нижний предел правильный. Это неверно, по крайней мере, не во всех случаях.
Модальные диалоги часто заботятся о перекачке самих событий AWT. Если вы запустите код
SwingUtilities.invokeAndWait(new Runnable()
{
public void run()
{
JOptionPane.showInputDialog("hello");
}
});
а затем перерыв, глядя на потоки, вы увидите только один поток EventQueue. Метод show() для JOptionPane сам включает в себя события.
Рамки, такие как Spin, и Foxtrot используют тот же подход - они позволяют вам создать долговременный метод блокировки на EDT, но следить за событиями, происходящими от самих событий накачки. Возможно, что качание имеет несколько потоков отправки (я уверен, что это было в случае с более старыми версиями swing), но теперь, когда многоядерность распространена, проблемы concurrency, в частности обеспечение изменений в одном потоке, правильно публикуются для других потоки, означают, что использование нескольких EDT создает ошибки в текущей реализации. Видеть
Несколько событий рассылки событий Swing