我创建了一个面板,在该面板上绘制了一组对象。每个对象都作为鼠标事件监听器添加到面板。据我所知,在事件发生后,通知监听器并且代码可能(或是?)在多个线程中执行。是否可以附加将在所有侦听器完成执行代码后执行的自定义代码?
答案 0 :(得分:3)
在同一个线程(事件调度程序线程)中执行。
要执行您想要的操作,您只需添加一个额外的侦听器,并让该侦听器调用SwingUtilities类的“executeLater”方法。
做什么,是等待EDT线程完成通知,然后调用你的代码。
要测试它,请添加此侦听器并查看其功能:
class MouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
// System.out.println("If uncommented this would be invoked with the rest of the listners");
SwingUtilities.invokeLater( new Runnable() {
public void run() {
System.out.println("Invoked after all the listeners were notified");
}
}
}
}
当然,这是一个老鼠听众你所拥有的。所有其他听众的概念都是一样的。
答案 1 :(得分:1)
至于诺埃尔评论:
这种技术可能会引起关注的一个问题是,特定的侦听器实现是否提前返回通知,并在单独的线程上执行“带外”工作。在这种情况下,通知调用的结束实际上并不标记侦听器执行的结束。如果这是一个实际的问题(即,您知道并关注其他用户定义的,精心制作的侦听器,那么您可能需要优化并重新审视该问题。
使用SwingUtilities.invokeLater()
,您确定在通知所有侦听器后执行代码。但是其中一个听众可能会在一个单独的线程中执行它的工作。
如果您需要在所有听众不仅收到通知但他们完成工作后才能执行您的代码,您可以执行以下操作:
<子>伪代码:子>
Listener implements MouseListener
+mouseClicked( event: MouseEvent )
SwingUtilities.invokeLater( // returns immediately
someTask()
)
-someTask()
// perform some long task.
如果你有听众
addListener( new Listener() )
addListener( new Listener() )
addListener( new Listener() )
addListener( new ExecuteAtTheEnd() )
如果所有(或某些)侦听器在不同的线程中执行其工作。您的ExecuteAtTheEnd
可能会在通知结束时执行代码,但不会在执行侦听器代码时执行。
那么,你做了什么?
您必须同步一些锁定标志的使用并执行您的代码,直到不使用该标志。
它可能是一个计数器,在监听器执行时递增,在不执行时递减:
Listener implements MouseListener
+mouseClicked( event: MouseEvent )
lockFlagCount++
SwingUtilities.invokeLater(
someTask()
)
-someTask()
// perform some long task.
lockFlag--
然后你继续直到这个标志为假:
ExecuteAtTheEndListener implements MouseListener
+ mouseClicked( event: MouseEvent )
SwingUtilities.invokeLater(
executeAtTheEnd()
)
- executeAtTheEnd()
while( logFlagCount > 0 )
wait()
if( logFlagCount == 0 )
// continue with the task.
当然,我把它放在伪代码中要复杂得多,但它应该有效,如果你处于这种情况下。
答案 2 :(得分:0)
我相信您需要的是使用SwingUtilities.invokeLater()
方法,该方法将在处理完所有其他GUI事件后在事件调度线程上调用Runnable实例。