3

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

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

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

4

2 回答 2

1

我没有看到任何这样做的方法。我想你可以做一些 hacky 的东西来制作你自己的注入更高优先级操作的方法。

不过,我认为最好的答案是根本不这样做。如果您需要这样做,则可能需要重新设计设计。EventDispatchThread 应该只用于运行时间很短的操作,因为它永远不会让最终用户看起来好像应用程序已冻结。正因为如此,EDT 的队列应该总是足够短,以至于从用户的角度来看,你放在它上面的任何东西都会“立即”发生,所以它上面的所有东西都应该具有“即时”优先级。

如果需要做的事情不是很短暂的行动,那么有一个单独的方法可以做到这一点。有一个Swing Worker类,您应该使用它来设置与 EDT 一起运行的任务并监听它的响应。

这是一个Swing Worker 教程。Google 还通过“Java SwingWorker 教程”查询提取了其他一些不错的内容。

于 2011-06-29T22:48:13.487 回答
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()and then 。pushFirst(e)不幸的是,队列将在异常时被卸载,并且也可能被推开。

接下来,为什么不好 的问题。总体而言,将事件放在队列的前面是一个坏主意。如果您稍后必须调用任何代码,只需构建您自己的设计并在函数结束时调用必要的代码,如果需要,请使用队列。

添加一个额外的超级最终优先级可能看起来不错,但对于任何常规 AWT/Swing(主要是 UI)开发人员来说,很难理解设计概念。如果您需要对操作进行排队,请使用您自己的迷你框架,而不会弄乱 awt。虽然我特别擅长黑客攻击,但即使是我自己,也会认为这种方法很奇怪(委婉地说)。

于 2011-06-29T23:36:30.070 回答