Java 在执行所有鼠标事件侦听器后调用代码
我已经创建了一个面板,在上面绘制了一组对象。每个对象都作为鼠标事件侦听器添加到面板中。正如我所知,事件发生后,监听器会收到通知,代码可能会(或正在?)在多个线程中执行。是否可以附加一个自定义代码,该代码将在所有侦听器执行完代码后执行?我相信您需要的是使用Java 在执行所有鼠标事件侦听器后调用代码,java,event-listener,Java,Event Listener,我已经创建了一个面板,在上面绘制了一组对象。每个对象都作为鼠标事件侦听器添加到面板中。正如我所知,事件发生后,监听器会收到通知,代码可能会(或正在?)在多个线程中执行。是否可以附加一个自定义代码,该代码将在所有侦听器执行完代码后执行?我相信您需要的是使用SwingUtilities.invokeLater()方法,该方法将在处理完所有其他GUI事件后调用事件调度线程上的可运行实例。我相信您需要的是使用SwingUtilities.invokeLater()方法,该方法将在处理所有其他GUI事件后
SwingUtilities.invokeLater()
方法,该方法将在处理完所有其他GUI事件后调用事件调度线程上的可运行实例。我相信您需要的是使用SwingUtilities.invokeLater()
方法,该方法将在处理所有其他GUI事件后调用事件调度线程上的可运行实例。在同一线程(事件调度线程)中执行
要做您想要做的事情,您只需添加一个额外的侦听器,并让该侦听器调用类的“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");
}
}
}
}
当然,你拥有的是一个鼠标侦听器。所有其他侦听器的概念都是相同的。在同一线程(事件调度程序线程)中执行 要做您想要做的事情,您只需添加一个额外的侦听器,并让该侦听器调用类的“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");
}
}
}
}
当然,你拥有的是一个鼠标侦听器。所有其他听众的想法都是一样的。至于Noel comment:
这种技术可能会遇到的一个问题是,如果特定的侦听器实现提前返回通知,并在单独的线程上执行“带外”工作。在这种情况下,通知调用的结束实际上并不表示侦听器执行的结束。如果这是一个实际的问题(即,您知道并关心其他用户定义的、精心设计的侦听器做这类事情),那么您可能需要改进并重新审视这个问题
使用SwingUtilities.invokeLater()
可以确保在通知所有侦听器之后执行代码。但是其中一个侦听器可能在单独的线程中执行其工作
如果您需要在所有侦听器不仅收到通知而且完成工作后执行代码,您可以执行以下操作:
伪代码:
如果你有你的听众
addListener( new Listener() )
addListener( new Listener() )
addListener( new Listener() )
addListener( new ExecuteAtTheEnd() )
如果您的所有(或部分)侦听器在不同的线程中执行其工作,则您的执行结束
可能会在通知结束时执行其代码,但不会在侦听器代码执行结束时执行
那么,你是做什么的
您必须同步某些锁定标志的使用,并执行代码,直到不使用该标志为止
它可能是一个计数器,在侦听器执行时递增,在不执行时递减:
Listener implements MouseListener
+mouseClicked( event: MouseEvent )
lockFlagCount++
SwingUtilities.invokeLater(
someTask()
)
-someTask()
// perform some long task.
lockFlag--
然后继续,直到这个标志为false:
ExecuteAtTheEndListener implements MouseListener
+ mouseClicked( event: MouseEvent )
SwingUtilities.invokeLater(
executeAtTheEnd()
)
- executeAtTheEnd()
while( logFlagCount > 0 )
wait()
if( logFlagCount == 0 )
// continue with the task.
当然,它比我在伪代码中所说的要复杂得多,但如果你处于这种情况,它应该可以工作。至于Noel评论:
这种技术可能会遇到的一个问题是,特定的侦听器实现是否提前返回通知,并在单独的线程上执行“带外”工作。在这种情况下,通知调用的结束实际上并不表示侦听器执行的结束。如果这是一个实际问题(也就是说,如果您知道并关心其他用户定义的、精心设计的监听器会做这类事情,那么您可能希望改进并重新审视这个问题
使用SwingUtilities.invokeLater()
可以确保在通知所有侦听器之后执行代码。但是其中一个侦听器可能在单独的线程中执行其工作
如果您需要在所有侦听器不仅收到通知而且完成工作后执行代码,您可以执行以下操作:
伪代码:
如果你有你的听众
addListener( new Listener() )
addListener( new Listener() )
addListener( new Listener() )
addListener( new ExecuteAtTheEnd() )
如果您的所有(或部分)侦听器在不同的线程中执行其工作,则您的执行结束
可能会在通知结束时执行其代码,但不会在侦听器代码执行结束时执行
那么,你是做什么的
您必须同步某些锁定标志的使用,并执行代码,直到不使用该标志为止
它可能是一个计数器,在侦听器执行时递增,在不执行时递减:
Listener implements MouseListener
+mouseClicked( event: MouseEvent )
lockFlagCount++
SwingUtilities.invokeLater(
someTask()
)
-someTask()
// perform some long task.
lockFlag--
然后继续,直到这个标志为false:
ExecuteAtTheEndListener implements MouseListener
+ mouseClicked( event: MouseEvent )
SwingUtilities.invokeLater(
executeAtTheEnd()
)
- executeAtTheEnd()
while( logFlagCount > 0 )
wait()
if( logFlagCount == 0 )
// continue with the task.
当然,正如我在伪代码中所说的那样,它要复杂得多,但如果您处于这种情况下,它应该可以工作。@czuk:这种技术可能会遇到的一个问题是,如果某个特定的侦听器实现提前返回通知,并在“带外”执行工作在单独的线程上。在这种情况下,通知调用的结束实际上并不表示侦听器执行的结束。如果这是一个实际问题(也就是说,你知道并关心其他用户定义的、精心设计的监听器会做这类事情,你可能会想改进并重新审视这个问题。@Noel:这是一个很好的观点。尽管监听器在长时间运行的任务(这是可取的)中使用不同的线程这一事实意味着它应该将他自己标记为“准备好接受更多”因此监听器代码实际上已经准备好了。另一种方法是使用共享标志,直到所有代码都准备好了才设置该标志……嗯,让我看看是否可以编写一些代码来更好地解释这一点。@Noel:你是指jvm开始以不同的方式执行监听器代码的情况吗