Я знаю, что это, вероятно, дурной ответ на мой собственный вопрос, но я пришел к выводу, что один должен обработчик событий очереди после события в Swing. Причина заключается в следующем: каждый компонент может иметь более одного слушателя данного типа. Вы не знаете, что слушатели слушают на любом данном компоненте (само свинг может добавить слушателей, о которых вы не подозреваете), и вы не знаете, какие предположения они делают относительно дерева компонентов, и состояние дерева, когда они обрабатывают событие.
Теперь, поскольку каждый компонент может иметь несколько обработчиков событий для определенного типа событий, мы не знаем, какой обработчик событий будет вызываться первым. Если мой обработчик событий модифицирует дерево компонентов, последующий обработчик событий для того же типа событий не увидит дерево компонентов, как это было во время события. Вместо этого он увидит дерево компонентов, как оно было после моих изменений. Та же проблема существует для другого состояния приложения, которое может быть проверено и изменено двумя отдельными слушателями одного типа на одном и том же компоненте. Это, конечно, не правильно.
Во-вторых, существует концепция событий, отправляемых EDT в последовательном порядке. то есть. Если событие x произошло до события y в режиме реального времени, тогда обработчики событий для x должны выполняться перед обработчиками событий для y . Теперь, если мой компонент, давайте назовем его c1 , имеет 2 обработчика событий для события actionPerformed()
- eh1 и eh2 . Когда actionPerformed()
срабатывает c1 , eh1 вызывается для обработки события. Затем он изменяет компонент c2 и вызывает событие itemStateChanged()
для c2 . Поскольку это изменение было поставлено в очередь после завершения первого события actionPerformed()
(позднее по EDT), а также потому, что c2 не ставит в очередь событие itemStateChanged()
для последующего запуска в EDT, событие itemStateChanged()
обрабатываются всеми его слушателями. Только тогда второй actionPerformed()
слушатель ( eh2 ) сможет обработать исходное событие actionPerformed()
.
Если eh2 также был прослушивателем itemStateChanged()
событий для компонента c2 , то eh2 может показаться, что событие itemStateChanged()
действительно произошло до события actionPerformed()
. Это тоже, безусловно, не так.
Таким образом, это отвечает на вопрос 1. Да, код обработки событий, который изменяет состояние приложения или дерево компонентов , должен быть запланирован для выполнения после обработки события. Обработчики событий должны проверять любое состояние, которое они должны проверять во время события, но реагировать на событие (вносить изменения) позже в EDT, вызывая EventQueue.invokeLater()
.
Вторая часть моего вопроса касается того, кто несет ответственность за обеспечение того, чтобы обработка событий происходила после того, как само событие произошло. Оглядываясь назад, это глупый вопрос. Та же проблема существует, если обработчики событий выполняются сразу же, когда происходит событие, или если они выполняются позднее компонентом, вызывающим EventQueue.invokeLater()
.
Между прочим, когда я исследовал это, я увидел, что не все компоненты Swing делают это равномерно. Например, JCheckBox
запускает события itemStateChanged()
сразу же, когда событие происходит, в то время как JComponent
запускает componentResized()
(через суперкласс java.awt.Component
) позже в EDT.
Таким образом, кажется, что наиболее надежный способ обработки событий - это сначала проверить ваше состояние, чтобы принять решение о том, какие действия вы предпримете, а затем выполнить эти действия позже в EDT. Какие-нибудь мысли? Я бы хотел услышать, как другие люди понимают это.