1

摆动事件处理代码是否应该在 EDT 上的事件之后排队?如果是这样,是事件源负责调度事件处理程序,还是事件处理程序负责稍后调度实际的处理代码?

考虑:

JButton b = new JButton();
b.addActionListener(新的ActionListener(){
    公共无效actionPerformed(ActionEvent e){
        /*
         * 剪辑 1
         * 做一些可能影响他人的事情
         * 组件或生成新事件...
         */

        // 剪辑 2
        EventQueue.invokeLater(new Runnable(){
            公共无效运行(){
                /*
                 * 做一些可能影响他人的事情
                 * 组件或生成新事件...
                 */
            }
        });
    }
});

SNIP 1收到事件时运行处理程序代码。如果由JButton负责安排事件EventQueue.invokeLater(),那么这可能是正确的。SNIP 2接收事件,并在接收到事件后负责调度处理程序代码(并由该特定事件类型的所有其他侦听器处理)。哪个是对的?

编辑:为了清楚起见,我想稍后在 EDT 上安排事件处理程序,因为在第一个事件处理程序中更改状态可能会在事件发生时隐藏组件的其他事件处理程序的原始状态。

4

3 回答 3

1

如果我误解了您的问题,请告诉我,但 Swing 事件侦听器中的所有代码都是在 EDT 上运行的,因此无需在 EDT 上排队。我很少看到像在 Swing 侦听器中使用的 snip2 之类的代码,通常是在侦听器在后台线程中调用匿名内部 Runnable 的情况下。

于 2011-02-06T06:23:50.267 回答
1

正如@HFOE 所指出的, 中的元素EventQueue顺序有序的;SNIP 2不应该是必需的。如果我理解您的要求,一种方法可能是将事件转发给任何其他感兴趣的听众,如本问答中所建议的那样。

于 2011-02-06T09:40:14.967 回答
1

我知道回答我自己的问题可能是一种不好的形式,但我得出的结论是,应该在 Swing 中的事件之后对事件处理程序进行排队。原因是这样的:每个组件可以有多个给定类型的侦听器。您不知道哪些侦听器正在侦听任何给定组件(swing 本身可能会添加您不知道的侦听器),并且您不知道它们对组件树做出了哪些假设,以及它们处理时树的状态一个事件。

现在,因为每个组件都可以有多个事件处理程序用于某种事件类型,所以我们不知道首先调用哪个事件处理程序。如果我的事件处理程序修改了组件树,则相同事件类型的后续事件处理程序将不会看到事件发生时的组件树。相反,它会看到我更改后的组件树。其他应用程序状态也存在相同的问题,这些应用程序状态可以由同一组件上的两个相同类型的单独侦听器检查和修改。这肯定是不对的。

其次,有一个事件由 EDT 按顺序分派的概念。IE。如果事件x实时发生在事件y之前,那么x的事件处理程序应该在y的事件处理程序之前运行。现在,如果我的组件,我们称之为c1,它有 2 个事件处理程序actionPerformed()- eh1eh2。当在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 上执行这些行动。有什么想法吗?我很想听听其他人对此的见解。

于 2011-02-07T15:50:26.933 回答