我正在寻找一种方法来执行InvokeLater()函数所做的事情,而不是将事件放在它放在顶部的事件队列的底部。至少我认为这会做我想要的,也许有更好的方法。下面描述了我想要复制的内容。
多年前,我在Mac上使用了一个c ++框架,它具有可以在处理当前事件时将Chore对象添加到CriticalChore列表的功能。你可以在执行相当于Swings EDT的代码时执行此操作。当前事件处理完毕并且在调用GetNextEvent()之前,Framework将检查CriticalChore列表是否为空。如果列表中有项目,则会调用Perform()(即run())函数。完成列表后,所有项目都被删除。
此功能非常方便。在早期处理事件时,很多时候你知道你需要执行一些额外的代码,但只有在处理了很多其他代码之后。但最重要的是,在处理来自EDT队列的任何其他事件之前,需要处理此代码。
答案 0 :(得分:1)
我没有看到任何这样做的方法。我想你可以做一些hacky的东西来制作你自己的注入更高优先级动作的方法。
我认为最好的答案是不要这样做。如果您需要这样做,设计可能需要重新设计。 EventDispatchThread应该仅适用于非常短时间运行的操作,因为它永远不应该向最终用户查看,就像应用程序已经冻结一样。因此,EDT的队列应该总是足够短,以至于你在其上放置的任何内容都会从用户的角度“立即”发生,因此其上的所有内容都应该具有“即时”优先级。
如果需要做任何不是非常短暂的行动的事情,那么有一种单独的方法可以做到这一点。有一个Swing Worker类,您应该使用它来设置与EDT一起运行的任务并听取其响应。
这是Swing Worker Tutorial。谷歌还提出了一些其他优秀的“Java SwingWorker教程”查询。
答案 1 :(得分:1)
首先,如何完成
可以安装一个具有自己队列的全局侦听器,每个事件轮询一个队列。 Toolkit.addAWTEventListener(listener, eventMask)
有一个sun.awt.PeerEvent
(对于sun impl)有ultimate priority
提供最简单的impl,因为它几乎与EventQueue.invokeLater延伸java.awt.event.InvocationEvent
相同,但同样不是标准。
最后: 这里是如何完成标准方式的,我还没有测试过代码(懒惰和非常晚)
class EventQueueX extends EventQueue{
final ConcurrentLinkedQueue<AWTEvent> que=new ConcurrentLinkedQueue<AWTEvent>();
@Override
public AWTEvent getNextEvent() throws InterruptedException {
AWTEvent e = que.poll();
if (e!=null)
return e;
return super.getNextEvent();
}
@Override
public synchronized AWTEvent peekEvent() {
AWTEvent e = que.peek();
if (e!=null)
return e;
return super.peekEvent();
}
public void pushFirst(AWTEvent e){
que.offer(e);
synchronized (this) {
notify();
}
}
public void install(Toolkit toolkit){
EventQueue q = toolkit.getSystemEventQueue();
if (q!=this)
q.push(this);
}
};
如果您想要举办活动,请使用EventQueueX.install()
,然后使用pushFirst(e)
。不幸的是,队列将在异常时被卸载,也可能被推开。
接下来,为什么不好 对于这个问题。将事件放在队列前面是一个坏主意。 如果您以后只需调用任何代码来构建您自己的设计,并在函数末尾调用必要的代码,请在需要时使用队列。
添加额外的超级终极优先级可能看起来不错,但对于任何常规的AWT / Swing(主要是UI)开发人员来说,这是一个难以理解的设计概念。如果你需要对行动进行排队,请使用自己的迷你框架,而不是使用awt。虽然我特别擅长黑客攻击,但即便是我,我自己也会采用这种方法做得很奇怪(温和地说)。