在EDT事件发生后,swing事件处理代码是否应该排队?如果是这样,事件源是否负责安排事件处理程序,或者事件处理程序是否有责任在以后安排实际处理代码?
考虑:
JButton b = new JButton(); b.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e){ /* * SNIP 1 * do something that may affect other * components or generate new events... */ // SNIP 2 EventQueue.invokeLater(new Runnable(){ public void run(){ /* * do something that may affect other * components or generate new events... */ } }); } });
SNIP 1
在收到事件时运行处理程序代码。如果JButton
负责按EventQueue.invokeLater()
安排事件,那么这可能是正确的。 SNIP 2
接收事件,并负责在收到事件后调度处理程序代码(并由此特定事件类型的所有其他侦听器处理)。哪个是对的?
编辑:为了清楚起见,我想稍后在EDT上安排事件处理程序,因为在第一个事件处理程序中更改状态可能会在事件发生时隐藏组件的其他事件处理程序的原始状态。
答案 0 :(得分:1)
如果我误解了您的问题,请告诉我,但是Swing事件监听器中的所有代码都是在EDT上运行的,因此无需将任何内容排队到EDT。我很少看到像在Swing监听器中使用的snip2中的代码,通常情况下,如果监听器在后台线程中调用匿名内部Runnable。
答案 1 :(得分:1)
正如@HFOE所说,EventQueue
中的元素是顺序和有序;不应要求SNIP 2
。如果我理解您的要求,一种方法可能是将事件转发任何其他感兴趣的听众,如question & answer中所述。
答案 2 :(得分:1)
我知道回答我自己的问题可能是一种糟糕的形式,但我得出的结论是,在事件中,一个应该对事件处理程序进行排队。原因是:每个组件可以有多个给定类型的侦听器。您不知道哪些侦听器正在侦听任何给定组件(swing本身可能会添加您不知道的侦听器),并且您不知道它们对组件树所做的假设以及它们处理时树的状态一个事件。
现在,因为每个组件可以具有针对特定事件类型的多个事件处理程序,所以我们不知道将首先调用哪个事件处理程序。如果我的事件处理程序修改了组件树,则同一事件类型的后续事件处理程序将不会像事件发生时那样看到组件树。相反,它会在我的更改后看到组件树。对于其他应用程序状态存在同样的问题,可以由同一组件上的两个相同类型的单独侦听器进行检查和修改。这肯定是不对的。
其次,EDT按顺序发送事件的概念。即。如果事件 x 在事件 y 之前实时发生,那么 x 的事件处理程序应该在 y <的事件处理程序之前运行/ em>的。现在,如果我的组件,我们称之为 c1 ,有2个事件处理程序用于事件actionPerformed()
- eh1 和 eh2 。在 c1 上触发actionPerformed()
时,会调用 eh1 来处理该事件。然后它修改组件 c2 ,并在 c2 上触发itemStateChanged()
事件。因为此更改在第一个actionPerformed()
事件完成后排队(在EDT之后),并且因为 c2 没有将itemStateChanged()
事件排队以便稍后在EDT上运行, itemStateChanged()
事件由其所有侦听器处理。只有这样,第二个actionPerformed()
侦听器( eh2 )才能处理原始actionPerformed()
事件。
如果 eh2 也是 c2 组件itemStateChanged()
事件的监听者,则 eh2 似乎{ {1}}事件实际发生在itemStateChanged()
事件之前。这也是肯定不对的。
这样回答问题1.是的,事件处理代码,修改应用程序状态或组件树应在事件处理后计划执行。事件处理程序应检查事件发生时需要检查的状态,但在EDT稍后通过调用actionPerformed()
对事件做出反应(进行更改)。
我的问题的第二部分是关于确保事件本身发生后事件处理的责任。事后来看,这是一个愚蠢的问题。如果在事件发生时立即执行事件处理程序,或者稍后由调用EventQueue.invokeLater()
的组件执行事件处理程序,则存在同样的问题。
顺便说一下,在我研究这个时,我发现并非所有的Swing组件都是统一的。例如,EventQueue.invokeLater()
会在事件发生时立即触发JCheckBox
事件,而itemStateChanged()
稍后会在EDT上触发JComponent
(通过超级componentResized()
)。
因此,处理事件最强大的方法似乎是首先检查您的状态以决定您将采取的操作,然后在EDT上执行这些操作。有什么想法吗?我很想听听其他人对此的见解。