在Swing中,您可以将事件发布到EDT事件队列的顶部吗?

时间:2011-06-29 22:22:18

标签: java events swing edt

我正在寻找一种方法来执行InvokeLater()函数所做的事情,而不是将事件放在它放在顶部的事件队列的底部。至少我认为这会做我想要的,也许有更好的方法。下面描述了我想要复制的内容。

多年前,我在Mac上使用了一个c ++框架,它具有可以在处理当前事件时将Chore对象添加到CriticalChore列表的功能。你可以在执行相当于Swings EDT的代码时执行此操作。当前事件处理完毕并且在调用GetNextEvent()之前,Framework将检查CriticalChore列表是否为空。如果列表中有项目,则会调用Perform()(即run())函数。完成列表后,所有项目都被删除。

此功能非常方便。在早期处理事件时,很多时候你知道你需要执行一些额外的代码,但只有在处理了很多其他代码之后。但最重要的是,在处理来自EDT队列的任何其他事件之前,需要处理此代码。

2 个答案:

答案 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。虽然我特别擅长黑客攻击,但即便是我,我自己也会采用这种方法做得很奇怪(温和地说)。