<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java Focus實現紀要二

    Posted on 2008-10-26 17:20 英雄 閱讀(1346) 評論(0)  編輯  收藏
     

    Java Focus實現紀要二

    1.       Jre1.7版本中,KeyboardFocusManagerDefaultKeyboardFocusManager這兩個類,Component, WComponentPeer類一起完成了focus的主要邏輯實現。

    DefaultKeyboardFocusManager是前者的系統(tǒng)默認實現。其單例注冊在appcontext,如果需要,程序員可以替代它,以擴展focus的邏輯實現。

    appcontext.put(KeyboardFocusManager.class, new SelfKeyboardFocusManager());

    2.       Component中提供了requestFocus方法。而各個組件在初始化時都會安裝默認的Listener。當這些Listener收到適當的事件通知后(比如mouse_press)即會調用這個方法。該方法首先判斷該組件是否focusable,組件所依托窗口是否focusable,當前聚焦組件的InputVerifier是否驗收輸入等等,判斷通過后請求重量級組件容器的peer.requestFocus。WComponentPeer中提供該requestFocus方法。該方法首先調用native processSynchronousLightweightTransfer,其會調用KeyboardFocusManager .processSynchronousLightweightTransferr,作用是如果當前request組件的重量級組件容器正對應當前底層系統(tǒng)的聚焦組件,而且當前沒有任何切換焦點的heavyweightRequests,這時將直接切換focus變量KeyboardFocusManager.focusOwner。

    如果上述調用沒有順利完成并返回true,則會調用native _requestFoucs。該方法會調用KeyboardFocusManager .shouldNativelyFocusHeavyweight,其作用就是完成request登記,并在登記時間戳以正確緩存處理后續(xù)進入EDTKeyevent處理。

    Request登記的結構為KeyboardFocusManager.heavyweightRequests=

    LinkedList< HeavyweightFocusRequest >

    -- HeavyweightFocusRequest{

    Component heavyweight;

    LinkedList<LightweightFocusRequest> lightweightRequests登記方式分為3:

    a. 如果發(fā)出requestFocus的組件的重量級組件容器正對應當前底層系統(tǒng)的聚焦組件,而且當前沒有任何切換焦點的heavyweightRequest,則增加一個heavyweightRequest并向Post-Qqeue post focus-event。

    b. 如果發(fā)出requestFocus組件的重量級組件容器不對應當前底層系統(tǒng)的聚焦組件,而且當前沒有任何切換焦點的heavyweightRequest;或者當前存在切換焦點的heavyweightRequest,而最后一個heavyweightRequest. Heavyweight!=當前request組件的重量級組件容器,則要增加一個heavyweightRequest,并同步通知底層系統(tǒng)進行重量級對等組件的focus切換。

    c. 如果當前存在切換焦點的heavyweightRequest,而且最后一個heavyweightRequest. Heavyweight==當前requestFocus的組件的重量級組件容器,則直接在request.lightweightRequests追加一個LightweightFocusRequest。

    3.       EDT在逐個處理AWTEvent時,委托給EventQueue.dispatchEvent,繼而委托給Component. dispatchEventImpl,該方法順序執(zhí)行下面的代碼片段:

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

    /* focusManagerIsDispatching標志了該event;如果==true意味著該event不會交由KeyboardManager進行retargetdispatch。而這兩個動作主要完成的功能就是刷新java的全局focus變量。因此可以想象focusManagerIsDispatching==trueFocus_eventfocus發(fā)生切換后的event,而focusManagerIsDispatching==false的是PrepareFocusEvent。*/

                if (!e.focusManagerIsDispatching) {//----------PrepareFocusEvent

                // Invoke the private focus retargeting method which provides

                // lightweight Component supportF

                /*通過retargetFocus,處理之前注冊的request請求,最終激發(fā)出合適的CausedFocusEvent,交給下面的dispatch.

     */

                if (e.isPosted) {

                    e = KeyboardFocusManager.retargetFocusEvent(e);

                    e.isPosted = true;

                }

                // Now, with the event properly targeted to a lightweight

                // descendant if necessary, invoke the public focus retargeting

                // and dispatching function

    /*通過dispatch給注冊的DefaultKeyboardFocusManager,最終更新了java的全局focus變量

     */

                if (KeyboardFocusManager.getCurrentKeyboardFocusManager().

                    dispatchEvent(e))

                {

                    return;

                }

            }

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

    4.       總之:

    a. 輕量級組件的Mouse_Press ListenerrequestFocus。request通過必要條件檢查后會在KeyboardFocusManager.heavyweightRequests緩存列表登記,同時在一個列表中登記一個時間戳marker=當前系統(tǒng)時間。

    b. 每一個KeyEvent都有一個發(fā)生時間when,這個發(fā)生時間認為是AWT-Windows loop底層event形成KeyEvent的時間。EDT在調用KeyboardFocusManager 。dispatchEvent處理一個KeyEvent時只要發(fā)現when晚于時間戳緩存列表中登記的第一個時間戳,就充分說明這是在某焦點切換請求發(fā)出后發(fā)生的鍵盤事件,則不應該將這個KeyEvent target到當前全局focus變量,因而這時暫將此KeyEvent緩存在另一個列表。

    c. 根據前面的分析,在requestFocus時有3種情況,一種是新增heavyweightRequest,同時postpost-queue一個FocusEvent,一種是新增heavyweightRequest,同時因為要求底層系統(tǒng)切換重量級對等體而awt-loop到一個FocusEvent,這兩種情況的request都在列表中期待對應FocusEvent到來再切換焦點。從登記時間戳開始,被awt-loop到的KeyEvent進入EDT時都將緩存下來,而一段時間后當期待的FocusEventpost-queue進入event-queue并要在EDT中處理時,有充分的條件可以判斷出此后再進入EDTKeyEvent,都至少是request登記時間戳后發(fā)生的,則這時可以完成此request-刪除該heavyweightRequest緩存條目,做focus實際切換,并將緩存的KeyEvent 及時間戳記錄處理掉。而第3種情況是在requestFocus時可以在最末一個heavyweightRequest上直接追加LightWeightReuquest,那么當該heavyweightRequest期待的FocusEvent到來時,按前面所述處理完該request,再將后續(xù)LightWeightRequest保存引用到一個全局變量KeyboardFocusManager.currentLightweightRequests,再將此刻為止awt-loop至的post-queue的所有event完全flushevent-queue,再把一個要求循環(huán)處理所有currentLightweightRequests指向的LightWeightRequestsInvocationEvent post event-queue之后。這樣當EDT開始處理該InvocationEvent時,有充分的條件可以判斷出此后再進入EDTKeyEvent,都至少是最后一個后續(xù)LightWeightRequest登記時間戳后發(fā)生的,則這時只需按該InvocationEvent執(zhí)行即可,及逐個清理LightWeightRequest完成focus切換及處理時間戳和緩存KeyEvent。如果在循環(huán)處理過程中發(fā)生對某一個組件requestFocus調用,這時會根據處理之初currentLightweightRequests中是否只有單獨1request來確定能否processSynchronousLightweightTransferr,即如果有多個,則這時禁止processSynchronousLightweightTransferr以防止破壞了切換焦點的順序。

    d. 重量級組件不需要在Mouse_Press Listener request Focus,當被進行Mouse Press時,底層系統(tǒng)分發(fā)一個Focus Event,當進入EDT處理時,在jre1.7中通過KeyboardFocusManager.retargetUnexpectedFocusEventretarget,首先逐個剔除request后進行期待匹配(針對可能的底層分發(fā)-post-queue-event-queue中間環(huán)節(jié)Event的遺漏等例外情形),如果最后沒有一個request匹配,則直接形成CausedFocusEvent交給后繼dispatch完成焦點切換。更確切地說,對于jre1.7而言組件聚焦應該都通過requestFocus完成切換,不通過該方式的聚焦切換在retarget時將歸屬到Unexpected被處理,而重量級組件的這種聚焦正好通過unexpected完成。

    5.       最后,個人認為jre1.7中存在一個可能的問題:每次dispatchEvent時都會在retargetFocusEventprocessCurrentLightweightRequests,這樣不久破壞了4-c分析的時機邏輯了么?為什么要這樣呢?


    只有注冊用戶登錄后才能發(fā)表評論。


    網站導航:
     
    主站蜘蛛池模板: 99视频精品全部免费观看| 最近国语视频在线观看免费播放| 亚洲日韩中文字幕日韩在线 | 无码人妻一区二区三区免费看| 国产成人亚洲影院在线观看| 牛牛在线精品观看免费正| 亚洲国产综合久久天堂| 亚洲欧洲在线播放| 国产人在线成免费视频| 亚洲人成激情在线播放| 无人在线观看免费高清视频 | 成人无码区免费A∨直播| 亚洲人成色7777在线观看| a级毛片无码免费真人久久| 久久精品国产69国产精品亚洲| 免费国产99久久久香蕉| 亚洲最大的视频网站| 成**人免费一级毛片| 一级毛片a免费播放王色电影 | 全免费a级毛片免费看不卡| 亚洲色大成网站www| 亚洲精品人成无码中文毛片 | 亚洲人成人网站在线观看| 成人毛片100免费观看| 亚洲一级二级三级不卡| 日韩欧美一区二区三区免费观看 | 亚洲一区精品中文字幕| 一个人免费高清在线观看| 美女视频黄a视频全免费网站一区| 亚洲精品狼友在线播放| 国产精品久久永久免费| 成a人片亚洲日本久久| 亚洲国产成人片在线观看| 97在线观免费视频观看| 人体大胆做受免费视频| 亚洲黄色免费网址| 五月天婷亚洲天综合网精品偷| 国产一区二区三区免费| 亚洲国产午夜精品理论片在线播放 | 好吊妞998视频免费观看在线| 成人福利在线观看免费视频|