我知道回答我自己的问题可能是一种不好的形式,但我得出的结论是,应该在 Swing 中的事件之后对事件处理程序进行排队。原因是这样的:每个组件可以有多个给定类型的侦听器。您不知道哪些侦听器正在侦听任何给定组件(swing 本身可能会添加您不知道的侦听器),并且您不知道它们对组件树做出了哪些假设,以及它们处理时树的状态一个事件。
现在,因为每个组件都可以有多个事件处理程序用于某种事件类型,所以我们不知道首先调用哪个事件处理程序。如果我的事件处理程序修改了组件树,则相同事件类型的后续事件处理程序将不会看到事件发生时的组件树。相反,它会看到我更改后的组件树。其他应用程序状态也存在相同的问题,这些应用程序状态可以由同一组件上的两个相同类型的单独侦听器检查和修改。这肯定是不对的。
其次,有一个事件由 EDT 按顺序分派的概念。IE。如果事件x实时发生在事件y之前,那么x的事件处理程序应该在y的事件处理程序之前运行。现在,如果我的组件,我们称之为c1,它有 2 个事件处理程序actionPerformed()
- eh1和eh2。当在c1actionPerformed()
上触发时,将调用eh1来处理事件。然后它修改组件c2,并在c2上触发一个事件。因为这个变化在第一个之后排队itemStateChanged()
actionPerformed()
事件已完成(稍后在 EDT 上),并且由于c2不会将itemStateChanged()
事件排队以稍后在 EDT 上运行,因此该itemStateChanged()
事件由其所有侦听器处理。只有这样,第二个actionPerformed()
侦听器 ( eh2 ) 才能处理原始actionPerformed()
事件。
如果eh2也是itemStateChanged()
组件c2上的事件的侦听器,那么在eh2 看来,该itemStateChanged()
事件实际上发生在该actionPerformed()
事件之前。这也肯定是不对的。
这样就回答了问题 1。是的,修改应用程序状态或组件树的事件处理代码应该安排在事件处理后执行。事件处理程序应在事件发生时检查他们需要检查的任何状态,但稍后在 EDT 上通过调用EventQueue.invokeLater()
.
我的问题的第二部分是关于谁负责确保在事件本身发生之后处理事件。事后看来,这是一个愚蠢的问题。如果事件处理程序在事件发生时立即执行,或者如果它们稍后由调用的组件执行,也会存在同样的问题EventQueue.invokeLater()
。
顺便说一句,在我研究这个的时候,我发现并不是所有的 Swing 组件都能做到这一点。例如,在事件发生时立即JCheckBox
触发itemStateChanged()
事件,而稍后在 EDT 上JComponent
触发componentResized()
(通过超类)。java.awt.Component
因此,处理事件的最稳健的方法似乎是首先检查您的状态以决定您将采取什么行动,然后在 EDT 上执行这些行动。有什么想法吗?我很想听听其他人对此的见解。