簡體   English   中英

在 Swing 中,您可以將事件發布到 EDT 事件隊列的頂部嗎?

[英]In Swing can you post an event to the top of the EDT events queue?

我正在尋找一種方法來執行 InvokeLater() function 所做的事情,而不是將事件放在事件隊列的底部,而是將其放在頂部。 至少我認為這會做我想要的,也許有更好的方法。 下面描述了我要復制的內容。

幾年前,我在 Mac 上使用了 c++ 框架,該框架具有可以在處理當前事件時將雜項 object 添加到關鍵雜項列表的功能。 您可以在執行相當於 Swings EDT 的代碼時執行此操作。 在當前事件完成處理之后,就在調用 GetNextEvent() 之前,框架將檢查 CriticalChore 列表是否為空。 如果列表中有項目,則將調用 Perform()(即 run())function。 完成列表后,所有項目都被刪除。

這個功能真的很方便。 很多時候,在早期處理事件時,您知道您需要執行一些額外的代碼,但只有在處理了許多其他代碼之后。 但最重要的是,是否需要在處理 EDT 隊列中的任何其他事件之前處理此代碼。

我沒有看到任何這樣做的方法。 我想你可以做一些 hacky 的東西來制作你自己的注入更高優先級操作的方法。

不過,我認為最好的答案是根本不這樣做。 如果您需要這樣做,則可能需要重新設計設計。 EventDispatchThread 應該只用於運行時間很短的操作,因為它永遠不會讓最終用戶看起來好像應用程序已凍結。 正因為如此,EDT 的隊列應該總是足夠短,以至於從用戶的角度來看,你放在它上面的任何東西都會“立即”發生,所以它上面的所有東西都應該具有“即時”優先級。

如果需要做的事情不是很短暫的行動,那么有一個單獨的方法可以做到這一點。 為此有一個Swing Worker class,您應該使用它來設置與 EDT 一起運行的任務並監聽其響應。

這是Swing 工人教程 Google 還通過“Java SwingWorker 教程”查詢提取了其他一些不錯的內容。

一、怎么做

可以安裝一個具有自己的隊列的全局偵聽器,並且每個事件都輪詢隊列。 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) 不幸的是,隊列將在異常時被卸載,並且也可能被推開。

接下來,為什么不好的問題。 總體而言,將事件放在隊列的前面是一個壞主意。 如果您稍后必須調用任何代碼,只需構建您自己的設計,並在 function 結束時調用必要的代碼,如果需要,請使用隊列。

添加一個額外的超級最終優先級可能看起來不錯,但對於任何常規 AWT/Swing(主要是 UI)開發人員來說,很難理解設計概念。 如果您需要對操作進行排隊,請使用您自己的迷你框架,而不會弄亂 awt。 雖然我特別擅長黑客攻擊,但即使是我自己,也會認為這種方法很奇怪(委婉地說)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM